blob: 70033c2aa470c4afc49d03f50c0d8c61ef78c331 [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
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
44#include <cdf_trace.h>
45#ifdef CONFIG_CNSS
46#include <net/cnss.h>
47#endif
48#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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080064#include "cdf_trace.h"
65#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"
72#include "wlan_hdd_misc.h"
73#include "wlan_hdd_nan.h"
74#include <wlan_hdd_ipa.h>
75#include "wlan_logging_sock_svc.h"
76
77#ifdef FEATURE_WLAN_EXTSCAN
78#include "wlan_hdd_ext_scan.h"
79#endif
80
81#ifdef WLAN_FEATURE_LINK_LAYER_STATS
82#include "wlan_hdd_stats.h"
83#endif
84#include "cds_concurrency.h"
85#include "qwlan_version.h"
86#include "wlan_hdd_memdump.h"
87
88#include "wlan_hdd_ocb.h"
89
Ravi Joshideb5a8d2015-11-09 19:11:43 -080090#include "wlan_hdd_subnet_detect.h"
91
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#define g_mode_rates_size (12)
93#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
95 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
96
97/*
98 * Android CTS verifier needs atleast this much wait time (in msec)
99 */
100#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
101
102/*
103 * Refer @tCfgProtection structure for definition of the bit map.
104 * below value is obtained by setting the following bit-fields.
105 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
106 */
107#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
108
109#define HDD2GHZCHAN(freq, chan, flag) { \
110 .band = IEEE80211_BAND_2GHZ, \
111 .center_freq = (freq), \
112 .hw_value = (chan), \
113 .flags = (flag), \
114 .max_antenna_gain = 0, \
115 .max_power = 30, \
116}
117
118#define HDD5GHZCHAN(freq, chan, flag) { \
119 .band = IEEE80211_BAND_5GHZ, \
120 .center_freq = (freq), \
121 .hw_value = (chan), \
122 .flags = (flag), \
123 .max_antenna_gain = 0, \
124 .max_power = 30, \
125}
126
127#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
128 { \
129 .bitrate = rate, \
130 .hw_value = rate_id, \
131 .flags = flag, \
132 }
133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
135#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136
137#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800138
Peng Xu4d67c8f2015-10-16 16:02:26 -0700139#define MAX_TXPOWER_SCALE 4
140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141static const u32 hdd_cipher_suites[] = {
142 WLAN_CIPHER_SUITE_WEP40,
143 WLAN_CIPHER_SUITE_WEP104,
144 WLAN_CIPHER_SUITE_TKIP,
145#ifdef FEATURE_WLAN_ESE
146#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
147#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
148 WLAN_CIPHER_SUITE_BTK,
149 WLAN_CIPHER_SUITE_KRK,
150 WLAN_CIPHER_SUITE_CCMP,
151#else
152 WLAN_CIPHER_SUITE_CCMP,
153#endif
154#ifdef FEATURE_WLAN_WAPI
155 WLAN_CIPHER_SUITE_SMS4,
156#endif
157#ifdef WLAN_FEATURE_11W
158 WLAN_CIPHER_SUITE_AES_CMAC,
159#endif
160};
161
162static struct ieee80211_channel hdd_channels_2_4_ghz[] = {
163 HDD2GHZCHAN(2412, 1, 0),
164 HDD2GHZCHAN(2417, 2, 0),
165 HDD2GHZCHAN(2422, 3, 0),
166 HDD2GHZCHAN(2427, 4, 0),
167 HDD2GHZCHAN(2432, 5, 0),
168 HDD2GHZCHAN(2437, 6, 0),
169 HDD2GHZCHAN(2442, 7, 0),
170 HDD2GHZCHAN(2447, 8, 0),
171 HDD2GHZCHAN(2452, 9, 0),
172 HDD2GHZCHAN(2457, 10, 0),
173 HDD2GHZCHAN(2462, 11, 0),
174 HDD2GHZCHAN(2467, 12, 0),
175 HDD2GHZCHAN(2472, 13, 0),
176 HDD2GHZCHAN(2484, 14, 0),
177};
178
179static struct ieee80211_channel hdd_social_channels_2_4_ghz[] = {
180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2437, 6, 0),
182 HDD2GHZCHAN(2462, 11, 0),
183};
184
185static struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186 HDD5GHZCHAN(5180, 36, 0),
187 HDD5GHZCHAN(5200, 40, 0),
188 HDD5GHZCHAN(5220, 44, 0),
189 HDD5GHZCHAN(5240, 48, 0),
190 HDD5GHZCHAN(5260, 52, 0),
191 HDD5GHZCHAN(5280, 56, 0),
192 HDD5GHZCHAN(5300, 60, 0),
193 HDD5GHZCHAN(5320, 64, 0),
194 HDD5GHZCHAN(5500, 100, 0),
195 HDD5GHZCHAN(5520, 104, 0),
196 HDD5GHZCHAN(5540, 108, 0),
197 HDD5GHZCHAN(5560, 112, 0),
198 HDD5GHZCHAN(5580, 116, 0),
199 HDD5GHZCHAN(5600, 120, 0),
200 HDD5GHZCHAN(5620, 124, 0),
201 HDD5GHZCHAN(5640, 128, 0),
202 HDD5GHZCHAN(5660, 132, 0),
203 HDD5GHZCHAN(5680, 136, 0),
204 HDD5GHZCHAN(5700, 140, 0),
205 HDD5GHZCHAN(5720, 144, 0),
206 HDD5GHZCHAN(5745, 149, 0),
207 HDD5GHZCHAN(5765, 153, 0),
208 HDD5GHZCHAN(5785, 157, 0),
209 HDD5GHZCHAN(5805, 161, 0),
210 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211 HDD5GHZCHAN(5852, 170, 0),
212 HDD5GHZCHAN(5855, 171, 0),
213 HDD5GHZCHAN(5860, 172, 0),
214 HDD5GHZCHAN(5865, 173, 0),
215 HDD5GHZCHAN(5870, 174, 0),
216 HDD5GHZCHAN(5875, 175, 0),
217 HDD5GHZCHAN(5880, 176, 0),
218 HDD5GHZCHAN(5885, 177, 0),
219 HDD5GHZCHAN(5890, 178, 0),
220 HDD5GHZCHAN(5895, 179, 0),
221 HDD5GHZCHAN(5900, 180, 0),
222 HDD5GHZCHAN(5905, 181, 0),
223 HDD5GHZCHAN(5910, 182, 0),
224 HDD5GHZCHAN(5915, 183, 0),
225 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226};
227
228static struct ieee80211_rate g_mode_rates[] = {
229 HDD_G_MODE_RATETAB(10, 0x1, 0),
230 HDD_G_MODE_RATETAB(20, 0x2, 0),
231 HDD_G_MODE_RATETAB(55, 0x4, 0),
232 HDD_G_MODE_RATETAB(110, 0x8, 0),
233 HDD_G_MODE_RATETAB(60, 0x10, 0),
234 HDD_G_MODE_RATETAB(90, 0x20, 0),
235 HDD_G_MODE_RATETAB(120, 0x40, 0),
236 HDD_G_MODE_RATETAB(180, 0x80, 0),
237 HDD_G_MODE_RATETAB(240, 0x100, 0),
238 HDD_G_MODE_RATETAB(360, 0x200, 0),
239 HDD_G_MODE_RATETAB(480, 0x400, 0),
240 HDD_G_MODE_RATETAB(540, 0x800, 0),
241};
242
243static struct ieee80211_rate a_mode_rates[] = {
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_supported_band wlan_hdd_band_2_4_ghz = {
255 .channels = hdd_channels_2_4_ghz,
256 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
257 .band = IEEE80211_BAND_2GHZ,
258 .bitrates = g_mode_rates,
259 .n_bitrates = g_mode_rates_size,
260 .ht_cap.ht_supported = 1,
261 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
262 | IEEE80211_HT_CAP_GRN_FLD
263 | IEEE80211_HT_CAP_DSSSCCK40
264 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
265 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
266 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
267 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
268 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
269 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
270 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
271};
272
273static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_ghz = {
274 .channels = hdd_social_channels_2_4_ghz,
275 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_ghz),
276 .band = IEEE80211_BAND_2GHZ,
277 .bitrates = g_mode_rates,
278 .n_bitrates = g_mode_rates_size,
279 .ht_cap.ht_supported = 1,
280 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
281 | IEEE80211_HT_CAP_GRN_FLD
282 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
283 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
284 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
285 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
286 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
287 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
288};
289
290static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
291 .channels = hdd_channels_5_ghz,
292 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
293 .band = IEEE80211_BAND_5GHZ,
294 .bitrates = a_mode_rates,
295 .n_bitrates = a_mode_rates_size,
296 .ht_cap.ht_supported = 1,
297 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
298 | IEEE80211_HT_CAP_GRN_FLD
299 | IEEE80211_HT_CAP_DSSSCCK40
300 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
301 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
302 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
303 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
304 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
305 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
306 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
307 .vht_cap.vht_supported = 1,
308};
309
310/* This structure contain information what kind of frame are expected in
311 TX/RX direction for each kind of interface */
312static const struct ieee80211_txrx_stypes
313 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
314 [NL80211_IFTYPE_STATION] = {
315 .tx = 0xffff,
316 .rx = BIT(SIR_MAC_MGMT_ACTION) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ),
318 },
319 [NL80211_IFTYPE_AP] = {
320 .tx = 0xffff,
321 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
322 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
323 BIT(SIR_MAC_MGMT_PROBE_REQ) |
324 BIT(SIR_MAC_MGMT_DISASSOC) |
325 BIT(SIR_MAC_MGMT_AUTH) |
326 BIT(SIR_MAC_MGMT_DEAUTH) |
327 BIT(SIR_MAC_MGMT_ACTION),
328 },
329 [NL80211_IFTYPE_ADHOC] = {
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_PROBE_REQ) |
334 BIT(SIR_MAC_MGMT_DISASSOC) |
335 BIT(SIR_MAC_MGMT_AUTH) |
336 BIT(SIR_MAC_MGMT_DEAUTH) |
337 BIT(SIR_MAC_MGMT_ACTION),
338 },
339 [NL80211_IFTYPE_P2P_CLIENT] = {
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ACTION) |
342 BIT(SIR_MAC_MGMT_PROBE_REQ),
343 },
344 [NL80211_IFTYPE_P2P_GO] = {
345 /* This is also same as for SoftAP */
346 .tx = 0xffff,
347 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
348 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ) |
350 BIT(SIR_MAC_MGMT_DISASSOC) |
351 BIT(SIR_MAC_MGMT_AUTH) |
352 BIT(SIR_MAC_MGMT_DEAUTH) |
353 BIT(SIR_MAC_MGMT_ACTION),
354 },
355};
356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357/* Interface limits and combinations registered by the driver */
358
359/* STA ( + STA ) combination */
360static const struct ieee80211_iface_limit
361 wlan_hdd_sta_iface_limit[] = {
362 {
363 .max = 3, /* p2p0 is a STA as well */
364 .types = BIT(NL80211_IFTYPE_STATION),
365 },
366};
367
Krunal Soni7bc4f912015-11-15 23:41:56 -0800368#ifndef QCA_WIFI_3_0_EMU
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369/* ADHOC (IBSS) limit */
370static const struct ieee80211_iface_limit
371 wlan_hdd_adhoc_iface_limit[] = {
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_STATION),
375 },
376 {
377 .max = 1,
378 .types = BIT(NL80211_IFTYPE_ADHOC),
379 },
380};
Krunal Soni7bc4f912015-11-15 23:41:56 -0800381#else
382/* ADHOC (IBSS) limit */
383static const struct ieee80211_iface_limit
384 wlan_hdd_adhoc_iface_limit[] = {
385 {
386 .max = 1,
387 .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
388 },
389 {
390 .max = 1,
391 .types = BIT(NL80211_IFTYPE_ADHOC),
392 },
393};
394#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800395
396/* AP ( + AP ) combination */
397static const struct ieee80211_iface_limit
398 wlan_hdd_ap_iface_limit[] = {
399 {
400 .max = (CDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
401 .types = BIT(NL80211_IFTYPE_AP),
402 },
403};
404
405/* P2P limit */
406static const struct ieee80211_iface_limit
407 wlan_hdd_p2p_iface_limit[] = {
408 {
409 .max = 1,
410 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
411 },
412 {
413 .max = 1,
414 .types = BIT(NL80211_IFTYPE_P2P_GO),
415 },
416};
417
418static const struct ieee80211_iface_limit
419 wlan_hdd_sta_ap_iface_limit[] = {
420 {
421 /* We need 1 extra STA interface for OBSS scan when SAP starts
422 * with HT40 in STA+SAP concurrency mode
423 */
424 .max = (1 + SAP_MAX_OBSS_STA_CNT),
425 .types = BIT(NL80211_IFTYPE_STATION),
426 },
427 {
428 .max = CDF_MAX_NO_OF_SAP_MODE,
429 .types = BIT(NL80211_IFTYPE_AP),
430 },
431};
432
433/* STA + P2P combination */
434static const struct ieee80211_iface_limit
435 wlan_hdd_sta_p2p_iface_limit[] = {
436 {
437 /* One reserved for dedicated P2PDEV usage */
438 .max = 2,
439 .types = BIT(NL80211_IFTYPE_STATION)
440 },
441 {
442 /* Support for two identical (GO + GO or CLI + CLI)
443 * or dissimilar (GO + CLI) P2P interfaces
444 */
445 .max = 2,
446 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
447 },
448};
449
450/* STA + AP + P2PGO combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
453 /* Support for AP+P2PGO interfaces */
454 {
455 .max = 2,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO)
461 },
462 {
463 .max = 1,
464 .types = BIT(NL80211_IFTYPE_AP)
465 }
466};
467
468/* SAP + P2P combination */
469static const struct ieee80211_iface_limit
470wlan_hdd_sap_p2p_iface_limit[] = {
471 {
472 /* 1 dedicated for p2p0 which is a STA type */
473 .max = 1,
474 .types = BIT(NL80211_IFTYPE_STATION)
475 },
476 {
477 /* The p2p interface in SAP+P2P can be GO/CLI.
478 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
479 */
480 .max = 1,
481 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
482 },
483 {
484 /* SAP+GO to support only one SAP interface */
485 .max = 1,
486 .types = BIT(NL80211_IFTYPE_AP)
487 }
488};
489
490/* P2P + P2P combination */
491static const struct ieee80211_iface_limit
492wlan_hdd_p2p_p2p_iface_limit[] = {
493 {
494 /* 1 dedicated for p2p0 which is a STA type */
495 .max = 1,
496 .types = BIT(NL80211_IFTYPE_STATION)
497 },
498 {
499 /* The p2p interface in P2P+P2P can be GO/CLI.
500 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
501 */
502 .max = 2,
503 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
504 },
505};
506
507static struct ieee80211_iface_combination
508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + CDF_MAX_NO_OF_SAP_MODE),
528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + CDF_MAX_NO_OF_SAP_MODE),
542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
584};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586static struct cfg80211_ops wlan_hdd_cfg80211_ops;
587
588
589#ifdef WLAN_NL80211_TESTMODE
590enum wlan_hdd_tm_attr {
591 WLAN_HDD_TM_ATTR_INVALID = 0,
592 WLAN_HDD_TM_ATTR_CMD = 1,
593 WLAN_HDD_TM_ATTR_DATA = 2,
594 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
595 WLAN_HDD_TM_ATTR_TYPE = 4,
596 /* keep last */
597 WLAN_HDD_TM_ATTR_AFTER_LAST,
598 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
599};
600
601enum wlan_hdd_tm_cmd {
602 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
603 WLAN_HDD_TM_CMD_WLAN_HB = 1,
604};
605
606#define WLAN_HDD_TM_DATA_MAX_LEN 5000
607
608static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
609 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
610 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
611 .len = WLAN_HDD_TM_DATA_MAX_LEN},
612};
613#endif /* WLAN_NL80211_TESTMODE */
614
615#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
616static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
617 .flags = WIPHY_WOWLAN_MAGIC_PKT,
618 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
619 .pattern_min_len = 1,
620 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
621};
622#endif
623
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530625 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
626 * @flags: Pointer to the flags to Add channel switch flag.
627 *
628 * This Function adds Channel Switch support flag, if channel switch is
629 * supported by kernel.
630 * Return: void.
631 */
632#ifdef CHANNEL_SWITCH_SUPPORTED
633static inline void hdd_add_channel_switch_support(uint32_t *flags)
634{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800635 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 return;
637}
638#else
639static inline void hdd_add_channel_switch_support(uint32_t *flags)
640{
641 return;
642}
643#endif
644
Manikandan Mohan22b83722015-12-15 15:03:23 -0800645#ifdef FEATURE_WLAN_TDLS
646
647/* TDLS capabilities params */
648#define PARAM_MAX_TDLS_SESSION \
649 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
650#define PARAM_TDLS_FEATURE_SUPPORT \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
652
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530653/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
655 * @wiphy: WIPHY structure pointer
656 * @wdev: Wireless device structure pointer
657 * @data: Pointer to the data received
658 * @data_len: Length of the data received
659 *
660 * This function provides TDLS capabilities
661 *
662 * Return: 0 on success and errno on failure
663 */
664static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
665 struct wireless_dev *wdev,
666 const void *data,
667 int data_len)
668{
669 int status;
670 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
671 struct sk_buff *skb;
672 uint32_t set = 0;
673
Anurag Chouhan6d760662016-02-20 16:05:43 +0530674 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 hdd_err("Command not allowed in FTM mode");
676 return -EPERM;
677 }
678
679 status = wlan_hdd_validate_context(hdd_ctx);
680 if (status)
681 return status;
682
683 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
684 NLMSG_HDRLEN);
685 if (!skb) {
686 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
687 goto fail;
688 }
689
690 if (false == hdd_ctx->config->fEnableTDLSSupport) {
691 hddLog(LOGE,
692 FL("TDLS feature not Enabled or Not supported in FW"));
693 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
694 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
695 hddLog(LOGE, FL("nla put fail"));
696 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);
704 hddLog(LOG1, FL("TDLS Feature supported value %x"), set);
705 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)) {
709 hddLog(LOGE, FL("nla put fail"));
710 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) {
766 hddLog(LOGE, FL("HDD context is null"));
767 return -EINVAL;
768 }
769
770 if (!pAvoidFreqList) {
771 hddLog(LOGE, FL("pAvoidFreqList is null"));
772 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) {
781 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
782 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 */
1060 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1063 },
1064 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1067 },
1068 /* OCB events */
1069 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1072 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001073#ifdef FEATURE_LFR_SUBNET_DETECTION
1074 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1075 .vendor_id = QCA_NL80211_VENDOR_ID,
1076 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1077 },
1078#endif /*FEATURE_LFR_SUBNET_DETECTION */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001079};
1080
1081/**
1082 * __is_driver_dfs_capable() - get driver DFS capability
1083 * @wiphy: pointer to wireless wiphy structure.
1084 * @wdev: pointer to wireless_dev structure.
1085 * @data: Pointer to the data to be passed via vendor interface
1086 * @data_len:Length of the data to be passed
1087 *
1088 * This function is called by userspace to indicate whether or not
1089 * the driver supports DFS offload.
1090 *
1091 * Return: 0 on success, negative errno on failure
1092 */
1093static int __is_driver_dfs_capable(struct wiphy *wiphy,
1094 struct wireless_dev *wdev,
1095 const void *data,
1096 int data_len)
1097{
1098 u32 dfs_capability = 0;
1099 struct sk_buff *temp_skbuff;
1100 int ret_val;
1101 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1102
1103 ENTER();
1104
1105 ret_val = wlan_hdd_validate_context(hdd_ctx);
1106 if (ret_val)
1107 return ret_val;
1108
Anurag Chouhan6d760662016-02-20 16:05:43 +05301109 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001110 hdd_err("Command not allowed in FTM mode");
1111 return -EPERM;
1112 }
1113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115
1116 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1117 NLMSG_HDRLEN);
1118
1119 if (temp_skbuff != NULL) {
1120 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1121 dfs_capability);
1122 if (ret_val) {
1123 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail"));
1124 kfree_skb(temp_skbuff);
1125
1126 return ret_val;
1127 }
1128
1129 return cfg80211_vendor_cmd_reply(temp_skbuff);
1130 }
1131
1132 hddLog(LOGE, FL("dfs capability: buffer alloc fail"));
1133 return -ENOMEM;
1134}
1135
1136/**
1137 * is_driver_dfs_capable() - get driver DFS capability
1138 * @wiphy: pointer to wireless wiphy structure.
1139 * @wdev: pointer to wireless_dev structure.
1140 * @data: Pointer to the data to be passed via vendor interface
1141 * @data_len:Length of the data to be passed
1142 *
1143 * This function is called by userspace to indicate whether or not
1144 * the driver supports DFS offload. This is an SSR-protected
1145 * wrapper function.
1146 *
1147 * Return: 0 on success, negative errno on failure
1148 */
1149static int is_driver_dfs_capable(struct wiphy *wiphy,
1150 struct wireless_dev *wdev,
1151 const void *data,
1152 int data_len)
1153{
1154 int ret;
1155
1156 cds_ssr_protect(__func__);
1157 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1158 cds_ssr_unprotect(__func__);
1159
1160 return ret;
1161}
1162
1163/**
1164 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1165 *
1166 * @adapter: SAP adapter pointer
1167 *
1168 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1169 * radio. So in case of DFS MCC scenario override current SAP given config
1170 * to follow concurrent SAP DFS config
1171 *
1172 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1173 */
1174
1175#ifdef WLAN_FEATURE_MBSSID
1176int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1177{
1178 hdd_adapter_t *con_sap_adapter;
1179 tsap_Config_t *sap_config, *con_sap_config;
1180 int con_ch;
1181
1182 /*
1183 * Check if AP+AP case, once primary AP chooses a DFS
1184 * channel secondary AP should always follow primary APs channel
1185 */
1186 if (!cds_concurrent_beaconing_sessions_running())
1187 return 0;
1188
1189 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1190 if (!con_sap_adapter)
1191 return 0;
1192
1193 sap_config = &adapter->sessionCtx.ap.sapConfig;
1194 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1195 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1196
1197 if (!CDS_IS_DFS_CH(con_ch))
1198 return 0;
1199
1200 hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"),
1201 sap_config->channel, con_ch);
1202 hddLog(LOG1, FL("Overriding guest AP's channel"));
1203 sap_config->channel = con_ch;
1204
1205 if (con_sap_config->acs_cfg.acs_mode == true) {
1206 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1207 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
1208 hddLog(LOGE, FL("Primary AP channel config error"));
1209 hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"),
1210 con_ch, con_sap_config->acs_cfg.pri_ch,
1211 con_sap_config->acs_cfg.ht_sec_ch);
1212 return -EINVAL;
1213 }
1214 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1215 * MCC restriction. So free ch list allocated in do_acs
1216 * func for Sec AP and realloc for Pri AP ch list size
1217 */
1218 if (sap_config->acs_cfg.ch_list)
1219 cdf_mem_free(sap_config->acs_cfg.ch_list);
1220
1221 cdf_mem_copy(&sap_config->acs_cfg,
1222 &con_sap_config->acs_cfg,
1223 sizeof(struct sap_acs_cfg));
1224 sap_config->acs_cfg.ch_list = cdf_mem_malloc(
1225 sizeof(uint8_t) *
1226 con_sap_config->acs_cfg.ch_list_count);
1227 if (!sap_config->acs_cfg.ch_list) {
1228 hddLog(LOGE, FL("ACS config alloc fail"));
1229 return -ENOMEM;
1230 }
1231
1232 cdf_mem_copy(sap_config->acs_cfg.ch_list,
1233 con_sap_config->acs_cfg.ch_list,
1234 con_sap_config->acs_cfg.ch_list_count);
1235
1236 } else {
1237 sap_config->acs_cfg.pri_ch = con_ch;
1238 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1239 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1240 }
1241
1242 return con_ch;
1243}
1244#else
1245int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1246{
1247 return 0;
1248}
1249#endif
1250
1251/**
1252 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1253 * @sap_cfg: pointer to SAP config struct
1254 *
1255 * This function sets the default ACS start and end channel for the given band
1256 * and also parses the given ACS channel list.
1257 *
1258 * Return: None
1259 */
1260
1261static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1262 bool vht_enabled)
1263{
1264 int i;
1265 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1266 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001267 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1);
1268 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1270 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001271 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1);
1272 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001273 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1274 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001275 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_36);
1276 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001277 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1278 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001279 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1);
1280 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281 }
1282
1283 if (ht_enabled)
1284 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1285
1286 if (vht_enabled)
1287 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1288
1289
1290 /* Parse ACS Chan list from hostapd */
1291 if (!sap_cfg->acs_cfg.ch_list)
1292 return;
1293
1294 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1295 sap_cfg->acs_cfg.end_ch =
1296 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1297 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
1298 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i])
1299 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1300 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1301 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1302 }
1303}
1304
1305
1306static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1307
1308/**
1309 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1310 * @adapter: pointer to SAP adapter struct
1311 *
1312 * This function starts the ACS procedure if there are no
1313 * constraints like MBSSID DFS restrictions.
1314 *
1315 * Return: Status of ACS Start procedure
1316 */
1317
1318static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1319{
1320
1321 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1322 tsap_Config_t *sap_config;
1323 tpWLAN_SAPEventCB acs_event_callback;
1324 int status;
1325
1326 sap_config = &adapter->sessionCtx.ap.sapConfig;
1327 sap_config->channel = AUTO_CHANNEL_SELECT;
1328
1329 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1330 if (status < 0) {
1331 return status;
1332 } else {
1333 if (status > 0) {
1334 /*notify hostapd about channel override */
1335 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1336 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1337 return 0;
1338 }
1339 }
1340 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1341 if (status) {
1342 hddLog(LOGE, FL("ACS config failed"));
1343 return -EINVAL;
1344 }
1345
1346 acs_event_callback = hdd_hostapd_sap_event_cb;
1347
1348 cdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301349 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350 hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex);
1351 status = wlansap_acs_chselect(
1352#ifdef WLAN_FEATURE_MBSSID
1353 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1354#else
1355 hdd_ctx->pcds_context,
1356#endif
1357 acs_event_callback, sap_config, adapter->dev);
1358
1359
1360 if (status) {
1361 hddLog(LOGE, FL("ACS channel select failed"));
1362 return -EINVAL;
1363 }
1364 sap_config->acs_cfg.acs_mode = true;
1365 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1366
1367 return 0;
1368}
1369
1370/**
1371 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1372 * @wiphy: Linux wiphy struct pointer
1373 * @wdev: Linux wireless device struct pointer
1374 * @data: ACS information from hostapd
1375 * @data_len: ACS information length
1376 *
1377 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1378 * and starts ACS procedure.
1379 *
1380 * Return: ACS procedure start status
1381 */
1382
1383static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1384 struct wireless_dev *wdev,
1385 const void *data, int data_len)
1386{
1387 struct net_device *ndev = wdev->netdev;
1388 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1390 tsap_Config_t *sap_config;
1391 struct sk_buff *temp_skbuff;
1392 int status = -EINVAL, i = 0;
1393 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1394 bool ht_enabled, ht40_enabled, vht_enabled;
1395 uint8_t ch_width;
1396
1397 /* ***Note*** Donot set SME config related to ACS operation here because
1398 * ACS operation is not synchronouse and ACS for Second AP may come when
1399 * ACS operation for first AP is going on. So only do_acs is split to
1400 * seperate start_acs routine. Also SME-PMAC struct that is used to
1401 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1402 * config shall be set only from start_acs.
1403 */
1404
1405 /* nla_policy Policy template. Policy not applied as some attributes are
1406 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1407 *
1408 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1409 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1410 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1411 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1412 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1413 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1414 */
1415
Anurag Chouhan6d760662016-02-20 16:05:43 +05301416 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 hdd_err("Command not allowed in FTM mode");
1418 return -EPERM;
1419 }
1420
1421 if (hdd_ctx->config->force_sap_acs) {
1422 hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled"));
1423 return -EPERM;
1424 }
1425
1426 status = wlan_hdd_validate_context(hdd_ctx);
1427 if (0 != status) {
1428 hddLog(LOGE, FL("HDD context is not valid"));
1429 goto out;
1430 }
1431 sap_config = &adapter->sessionCtx.ap.sapConfig;
1432 cdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
1433
1434 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1435 NULL);
1436 if (status) {
1437 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
1438 goto out;
1439 }
1440
1441 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
1442 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed"));
1443 goto out;
1444 }
1445 sap_config->acs_cfg.hw_mode = nla_get_u8(
1446 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1447
1448 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1449 ht_enabled =
1450 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1451 else
1452 ht_enabled = 0;
1453
1454 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1455 ht40_enabled =
1456 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1457 else
1458 ht40_enabled = 0;
1459
1460 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1461 vht_enabled =
1462 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1463 else
1464 vht_enabled = 0;
1465
1466 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1467 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1468 } else {
1469 if (ht_enabled && ht40_enabled)
1470 ch_width = 40;
1471 else
1472 ch_width = 20;
1473 }
1474 if (ch_width == 80)
1475 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1476 else if (ch_width == 40)
1477 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1478 else
1479 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1480
1481 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1482 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1483 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1484 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1485 * since it contains the frequency values of the channels in
1486 * the channel list.
1487 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1488 * is present
1489 */
1490 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1491 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1492 sap_config->acs_cfg.ch_list_count = nla_len(
1493 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1494 if (sap_config->acs_cfg.ch_list_count) {
1495 sap_config->acs_cfg.ch_list = cdf_mem_malloc(
1496 sizeof(uint8_t) *
1497 sap_config->acs_cfg.ch_list_count);
1498 if (sap_config->acs_cfg.ch_list == NULL)
1499 goto out;
1500
1501 cdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
1502 sap_config->acs_cfg.ch_list_count);
1503 }
1504 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1505 uint32_t *freq =
1506 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1507 sap_config->acs_cfg.ch_list_count = nla_len(
1508 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1509 sizeof(uint32_t);
1510 if (sap_config->acs_cfg.ch_list_count) {
1511 sap_config->acs_cfg.ch_list = cdf_mem_malloc(
1512 sap_config->acs_cfg.ch_list_count);
1513 if (sap_config->acs_cfg.ch_list == NULL) {
1514 hddLog(LOGE, FL("ACS config alloc fail"));
1515 status = -ENOMEM;
1516 goto out;
1517 }
1518
1519 /* convert frequency to channel */
1520 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1521 sap_config->acs_cfg.ch_list[i] =
1522 ieee80211_frequency_to_channel(freq[i]);
1523 }
1524 }
1525
1526 hdd_debug("get pcl for DO_ACS vendor command");
1527
1528 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001529 status = cds_get_pcl(CDS_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530 sap_config->acs_cfg.pcl_channels,
1531 &sap_config->acs_cfg.pcl_ch_count);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301532 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 hddLog(LOGE, FL("Get PCL failed"));
1534
1535 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1536
1537 /* ACS override for android */
1538 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
1539 hddLog(LOG1, FL("ACS Config override for 11AC"));
1540 vht_enabled = 1;
1541 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1542 sap_config->acs_cfg.ch_width =
1543 hdd_ctx->config->vhtChannelWidth;
1544 /* No VHT80 in 2.4G so perform ACS accordingly */
1545 if (sap_config->acs_cfg.end_ch <= 14 &&
1546 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1547 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1548 }
1549
1550 hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"),
1551 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1552 ch_width, ht_enabled, vht_enabled,
1553 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1554
1555 if (sap_config->acs_cfg.ch_list_count) {
1556 hddLog(LOG1, FL("ACS channel list: len: %d"),
1557 sap_config->acs_cfg.ch_list_count);
1558 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1559 hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]);
1560 }
1561 sap_config->acs_cfg.acs_mode = true;
1562 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
1563 /* ***Note*** Completion variable usage is not allowed here since
1564 * ACS scan operation may take max 2.2 sec for 5G band.
1565 * 9 Active channel X 40 ms active scan time +
1566 * 16 Passive channel X 110ms passive scan time
1567 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1568 * for this long. So we split up the scanning part.
1569 */
1570 set_bit(ACS_PENDING, &adapter->event_flags);
1571 hddLog(LOG1, FL("ACS Pending for wlan%d"),
1572 adapter->dev->ifindex);
1573 status = 0;
1574 } else {
1575 status = wlan_hdd_cfg80211_start_acs(adapter);
1576 }
1577
1578out:
1579 if (0 == status) {
1580 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1581 NLMSG_HDRLEN);
1582 if (temp_skbuff != NULL)
1583 return cfg80211_vendor_cmd_reply(temp_skbuff);
1584 }
1585
1586 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1587
1588 return status;
1589}
1590
1591 /**
1592 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1593 * @wiphy: Linux wiphy struct pointer
1594 * @wdev: Linux wireless device struct pointer
1595 * @data: ACS information from hostapd
1596 * @data_len: ACS information len
1597 *
1598 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1599 * and starts ACS procedure.
1600 *
1601 * Return: ACS procedure start status
1602 */
1603
1604static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1605 struct wireless_dev *wdev,
1606 const void *data, int data_len)
1607{
1608 int ret;
1609
1610 cds_ssr_protect(__func__);
1611 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1612 cds_ssr_unprotect(__func__);
1613
1614 return ret;
1615}
1616
1617/**
1618 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1619 * @work: Linux workqueue struct pointer for ACS work
1620 *
1621 * This function starts the ACS procedure which was marked pending when an ACS
1622 * procedure was in progress for a concurrent SAP interface.
1623 *
1624 * Return: None
1625 */
1626
1627static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1628{
1629 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1630 acs_pending_work.work);
1631 wlan_hdd_cfg80211_start_acs(adapter);
1632}
1633
1634/**
1635 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1636 * @adapter: Pointer to SAP adapter struct
1637 * @pri_channel: SAP ACS procedure selected Primary channel
1638 * @sec_channel: SAP ACS procedure selected secondary channel
1639 *
1640 * This is a callback function from SAP module on ACS procedure is completed.
1641 * This function send the ACS selected channel information to hostapd
1642 *
1643 * Return: None
1644 */
1645
1646void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1647{
1648 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1649 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1650 struct sk_buff *vendor_event;
1651 int ret_val;
1652 hdd_adapter_t *con_sap_adapter;
1653 uint16_t ch_width;
1654
1655 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1656 NULL,
1657 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1658 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1659 GFP_KERNEL);
1660
1661 if (!vendor_event) {
1662 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
1663 return;
1664 }
1665
1666 ret_val = hdd_vendor_put_ifindex(vendor_event, adapter->dev->ifindex);
1667 if (ret_val) {
1668 hddLog(LOGE, FL("NL80211_ATTR_IFINDEX put fail"));
1669 kfree_skb(vendor_event);
1670 return;
1671 }
1672
1673 ret_val = nla_put_u8(vendor_event,
1674 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1675 sap_cfg->acs_cfg.pri_ch);
1676 if (ret_val) {
1677 hddLog(LOGE,
1678 FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail"));
1679 kfree_skb(vendor_event);
1680 return;
1681 }
1682
1683 ret_val = nla_put_u8(vendor_event,
1684 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1685 sap_cfg->acs_cfg.ht_sec_ch);
1686 if (ret_val) {
1687 hddLog(LOGE,
1688 FL(
1689 "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail"));
1690 kfree_skb(vendor_event);
1691 return;
1692 }
1693
1694 ret_val = nla_put_u8(vendor_event,
1695 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1696 sap_cfg->acs_cfg.vht_seg0_center_ch);
1697 if (ret_val) {
1698 hddLog(LOGE,
1699 FL(
1700 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail"));
1701 kfree_skb(vendor_event);
1702 return;
1703 }
1704
1705 ret_val = nla_put_u8(vendor_event,
1706 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1707 sap_cfg->acs_cfg.vht_seg1_center_ch);
1708 if (ret_val) {
1709 hddLog(LOGE,
1710 FL(
1711 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail"));
1712 kfree_skb(vendor_event);
1713 return;
1714 }
1715
1716 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1717 ch_width = 80;
1718 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1719 ch_width = 40;
1720 else
1721 ch_width = 20;
1722
1723 ret_val = nla_put_u16(vendor_event,
1724 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1725 ch_width);
1726 if (ret_val) {
1727 hddLog(LOGE,
1728 FL(
1729 "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail"));
1730 kfree_skb(vendor_event);
1731 return;
1732 }
1733 if (sap_cfg->acs_cfg.pri_ch > 14)
1734 ret_val = nla_put_u8(vendor_event,
1735 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1736 QCA_ACS_MODE_IEEE80211A);
1737 else
1738 ret_val = nla_put_u8(vendor_event,
1739 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1740 QCA_ACS_MODE_IEEE80211G);
1741
1742 if (ret_val) {
1743 hddLog(LOGE,
1744 FL(
1745 "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail"));
1746 kfree_skb(vendor_event);
1747 return;
1748 }
1749
1750 hddLog(LOG1,
1751 FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"),
1752 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1753 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1754 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1755
1756 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1757 /* ***Note*** As already mentioned Completion variable usage is not
1758 * allowed here since ACS scan operation may take max 2.2 sec.
1759 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1760 * operation.
1761 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1762 * when Primary AP ACS is complete and secondary AP ACS is started here
1763 * immediately, Primary AP start_bss may come inbetween ACS operation
1764 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1765 * delay. This path and below constraint will be removed on sessionizing
1766 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1767 * As per design constraint user space control application must take
1768 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1769 * this code path. Sec AP hostapd should be started after Primary AP
1770 * start beaconing which can be confirmed by getchannel iwpriv command
1771 */
1772
1773 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1774 if (con_sap_adapter &&
1775 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
1776#ifdef CONFIG_CNSS
1777 cnss_init_delayed_work(&con_sap_adapter->acs_pending_work,
1778 wlan_hdd_cfg80211_start_pending_acs);
1779#else
1780 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1781 wlan_hdd_cfg80211_start_pending_acs);
1782#endif
1783 /* Lets give 500ms for OBSS + START_BSS to complete */
1784 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1785 msecs_to_jiffies(500));
1786 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1787 }
1788
1789 return;
1790}
1791
1792static int
1793__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1794 struct wireless_dev *wdev,
1795 const void *data,
1796 int data_len)
1797{
1798 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1799 struct sk_buff *skb = NULL;
1800 uint32_t fset = 0;
1801 int ret;
1802
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301803 ENTER();
1804
Anurag Chouhan6d760662016-02-20 16:05:43 +05301805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 hdd_err("Command not allowed in FTM mode");
1807 return -EPERM;
1808 }
1809
1810 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301811 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813
1814 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
1815 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
1816 fset |= WIFI_FEATURE_INFRA;
1817 }
1818 if (true == hdd_is_5g_supported(pHddCtx)) {
1819 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
1820 fset |= WIFI_FEATURE_INFRA_5G;
1821 }
1822#ifdef WLAN_FEATURE_P2P
1823 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1824 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
1825 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
1826 fset |= WIFI_FEATURE_P2P;
1827 }
1828#endif
1829 fset |= WIFI_FEATURE_SOFT_AP;
1830
1831 /* HOTSPOT is a supplicant feature, enable it by default */
1832 fset |= WIFI_FEATURE_HOTSPOT;
1833
1834#ifdef FEATURE_WLAN_EXTSCAN
1835 if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
1836 hddLog(LOG1, FL("EXTScan is supported by firmware"));
1837 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1838 }
1839#endif
1840 if (wlan_hdd_nan_is_supported()) {
1841 hddLog(LOG1, FL("NAN is supported by firmware"));
1842 fset |= WIFI_FEATURE_NAN;
1843 }
1844 if (sme_is_feature_supported_by_fw(RTT)) {
1845 hddLog(LOG1, FL("RTT is supported by firmware"));
1846 fset |= WIFI_FEATURE_D2D_RTT;
1847 fset |= WIFI_FEATURE_D2AP_RTT;
1848 }
1849#ifdef FEATURE_WLAN_SCAN_PNO
1850 if (pHddCtx->config->configPNOScanSupport &&
1851 sme_is_feature_supported_by_fw(PNO)) {
1852 hddLog(LOG1, FL("PNO is supported by firmware"));
1853 fset |= WIFI_FEATURE_PNO;
1854 }
1855#endif
1856 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1857#ifdef FEATURE_WLAN_TDLS
1858 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1859 sme_is_feature_supported_by_fw(TDLS)) {
1860 hddLog(LOG1, FL("TDLS is supported by firmware"));
1861 fset |= WIFI_FEATURE_TDLS;
1862 }
1863 if (sme_is_feature_supported_by_fw(TDLS) &&
1864 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1865 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
1866 hddLog(LOG1, FL("TDLS off-channel is supported by firmware"));
1867 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1868 }
1869#endif
1870#ifdef WLAN_AP_STA_CONCURRENCY
1871 fset |= WIFI_FEATURE_AP_STA;
1872#endif
1873 fset |= WIFI_FEATURE_RSSI_MONITOR;
1874
1875 if (hdd_link_layer_stats_supported())
1876 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1877
1878 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1879 NLMSG_HDRLEN);
1880 if (!skb) {
1881 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1882 return -EINVAL;
1883 }
1884 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
1885 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
1886 hddLog(LOGE, FL("nla put fail"));
1887 goto nla_put_failure;
1888 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301889 ret = cfg80211_vendor_cmd_reply(skb);
1890 EXIT();
1891 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892nla_put_failure:
1893 kfree_skb(skb);
1894 return -EINVAL;
1895}
1896
1897/**
1898 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1899 * @wiphy: pointer to wireless wiphy structure.
1900 * @wdev: pointer to wireless_dev structure.
1901 * @data: Pointer to the data to be passed via vendor interface
1902 * @data_len:Length of the data to be passed
1903 *
1904 * Return: Return the Success or Failure code.
1905 */
1906static int
1907wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1908 struct wireless_dev *wdev,
1909 const void *data, int data_len)
1910{
1911 int ret = 0;
1912
1913 cds_ssr_protect(__func__);
1914 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1915 data, data_len);
1916 cds_ssr_unprotect(__func__);
1917
1918 return ret;
1919}
1920
1921/**
1922 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1923 * @wiphy: pointer to wireless wiphy structure.
1924 * @wdev: pointer to wireless_dev structure.
1925 * @data: Pointer to the data to be passed via vendor interface
1926 * @data_len:Length of the data to be passed
1927 *
1928 * Set the MAC address that is to be used for scanning.
1929 *
1930 * Return: Return the Success or Failure code.
1931 */
1932static int
1933__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1934 struct wireless_dev *wdev,
1935 const void *data,
1936 int data_len)
1937{
1938 tpSirScanMacOui pReqMsg = NULL;
1939 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1940 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301941 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 int ret;
1943
1944 ENTER();
1945
Anurag Chouhan6d760662016-02-20 16:05:43 +05301946 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 hdd_err("Command not allowed in FTM mode");
1948 return -EPERM;
1949 }
1950
1951 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301952 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
1955 if (false == pHddCtx->config->enable_mac_spoofing) {
1956 hddLog(LOGW, FL("MAC address spoofing is not enabled"));
1957 return -ENOTSUPP;
1958 }
1959
1960 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1961 data, data_len, NULL)) {
1962 hddLog(LOGE, FL("Invalid ATTR"));
1963 return -EINVAL;
1964 }
1965 pReqMsg = cdf_mem_malloc(sizeof(*pReqMsg));
1966 if (!pReqMsg) {
1967 hddLog(LOGE, FL("cdf_mem_malloc failed"));
1968 return -ENOMEM;
1969 }
1970 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
1971 hddLog(LOGE, FL("attr mac oui failed"));
1972 goto fail;
1973 }
1974 nla_memcpy(&pReqMsg->oui[0],
1975 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1976 sizeof(pReqMsg->oui));
1977 hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0],
1978 pReqMsg->oui[1], pReqMsg->oui[2]);
1979 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301980 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 hddLog(CDF_TRACE_LEVEL_ERROR,
1982 FL("sme_set_scanning_mac_oui failed(err=%d)"), status);
1983 goto fail;
1984 }
1985 return 0;
1986fail:
1987 cdf_mem_free(pReqMsg);
1988 return -EINVAL;
1989}
1990
1991/**
1992 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1993 * @wiphy: pointer to wireless wiphy structure.
1994 * @wdev: pointer to wireless_dev structure.
1995 * @data: Pointer to the data to be passed via vendor interface
1996 * @data_len:Length of the data to be passed
1997 *
1998 * Set the MAC address that is to be used for scanning. This is an
1999 * SSR-protecting wrapper function.
2000 *
2001 * Return: Return the Success or Failure code.
2002 */
2003static int
2004wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2005 struct wireless_dev *wdev,
2006 const void *data,
2007 int data_len)
2008{
2009 int ret;
2010
2011 cds_ssr_protect(__func__);
2012 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2013 data, data_len);
2014 cds_ssr_unprotect(__func__);
2015
2016 return ret;
2017}
2018
2019/**
2020 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2021 * @feature_flags: pointer to the byte array of features.
2022 * @feature: Feature to be turned ON in the byte array.
2023 *
2024 * Return: None
2025 *
2026 * This is called to turn ON or SET the feature flag for the requested feature.
2027 **/
2028#define NUM_BITS_IN_BYTE 8
2029void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2030{
2031 uint32_t index;
2032 uint8_t bit_mask;
2033
2034 index = feature / NUM_BITS_IN_BYTE;
2035 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2036 feature_flags[index] |= bit_mask;
2037}
2038
2039/**
2040 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2041 * @wiphy: pointer to wireless wiphy structure.
2042 * @wdev: pointer to wireless_dev structure.
2043 * @data: Pointer to the data to be passed via vendor interface
2044 * @data_len:Length of the data to be passed
2045 *
2046 * This is called when wlan driver needs to send supported feature set to
2047 * supplicant upon a request/query from the supplicant.
2048 *
2049 * Return: Return the Success or Failure code.
2050 **/
2051#define MAX_CONCURRENT_CHAN_ON_24G 2
2052#define MAX_CONCURRENT_CHAN_ON_5G 2
2053static int
2054__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2055 struct wireless_dev *wdev,
2056 const void *data, int data_len)
2057{
2058 struct sk_buff *skb = NULL;
2059 uint32_t dbs_capability = 0;
2060 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302061 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 int ret_val;
2063
2064 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2065 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2066
2067 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2068 if (ret_val)
2069 return ret_val;
2070
Anurag Chouhan6d760662016-02-20 16:05:43 +05302071 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 hdd_err("Command not allowed in FTM mode");
2073 return -EPERM;
2074 }
2075
2076 if (hdd_ctx_ptr->config->isRoamOffloadEnabled) {
2077 hddLog(LOG1, FL("Key Mgmt Offload is supported"));
2078 wlan_hdd_cfg80211_set_feature(feature_flags,
2079 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2080 }
2081
2082 wlan_hdd_cfg80211_set_feature(feature_flags,
2083 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2084 if (wma_is_scan_simultaneous_capable())
2085 wlan_hdd_cfg80211_set_feature(feature_flags,
2086 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
2087 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2088 NLMSG_HDRLEN);
2089
2090 if (!skb) {
2091 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2092 return -ENOMEM;
2093 }
2094
2095 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2096 sizeof(feature_flags), feature_flags))
2097 goto nla_put_failure;
2098
2099 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302100 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002101 if (one_by_one_dbs)
2102 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2103
2104 if (two_by_two_dbs)
2105 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2106
2107 if (!one_by_one_dbs && !two_by_two_dbs)
2108 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2109 } else {
2110 hdd_err("wma_get_dbs_hw_mode failed");
2111 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2112 }
2113
2114 hdd_info("dbs_capability is %d", dbs_capability);
2115
2116 if (nla_put_u32(skb,
2117 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2118 MAX_CONCURRENT_CHAN_ON_24G))
2119 goto nla_put_failure;
2120
2121 if (nla_put_u32(skb,
2122 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2123 MAX_CONCURRENT_CHAN_ON_5G))
2124 goto nla_put_failure;
2125
2126 return cfg80211_vendor_cmd_reply(skb);
2127
2128nla_put_failure:
2129 kfree_skb(skb);
2130 return -EINVAL;
2131}
2132
2133/**
2134 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2135 * @wiphy: pointer to wireless wiphy structure.
2136 * @wdev: pointer to wireless_dev structure.
2137 * @data: Pointer to the data to be passed via vendor interface
2138 * @data_len:Length of the data to be passed
2139 *
2140 * This is called when wlan driver needs to send supported feature set to
2141 * supplicant upon a request/query from the supplicant.
2142 *
2143 * Return: Return the Success or Failure code.
2144 */
2145static int
2146wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2147 struct wireless_dev *wdev,
2148 const void *data, int data_len)
2149{
2150 int ret;
2151
2152 cds_ssr_protect(__func__);
2153 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2154 data, data_len);
2155 cds_ssr_unprotect(__func__);
2156
2157 return ret;
2158}
2159
2160
2161/**
2162 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2163 * @wiphy: The wiphy structure
2164 * @wdev: The wireless device
2165 * @data: Data passed by framework
2166 * @data_len: Parameters to be configured passed as data
2167 *
2168 * The roaming related parameters are configured by the framework
2169 * using this interface.
2170 *
2171 * Return: Return either success or failure code.
2172 */
2173static int
2174__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2175 struct wireless_dev *wdev, const void *data, int data_len)
2176{
2177 struct net_device *dev = wdev->netdev;
2178 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2179 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2180 uint8_t session_id;
2181 struct roam_ext_params roam_params;
2182 uint32_t cmd_type, req_id;
2183 struct nlattr *curr_attr;
2184 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2185 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2186 int rem, i;
2187 uint32_t buf_len = 0;
2188 int ret;
2189
Anurag Chouhan6d760662016-02-20 16:05:43 +05302190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 hdd_err("Command not allowed in FTM mode");
2192 return -EPERM;
2193 }
2194
2195 ret = wlan_hdd_validate_context(pHddCtx);
2196 if (0 != ret) {
2197 hddLog(LOGE, FL("HDD context is not valid"));
2198 return -EINVAL;
2199 }
2200
2201 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2202 data, data_len,
2203 NULL)) {
2204 hddLog(LOGE, FL("Invalid ATTR"));
2205 return -EINVAL;
2206 }
2207 /* Parse and fetch Command Type*/
2208 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
2209 hddLog(LOGE, FL("roam cmd type failed"));
2210 goto fail;
2211 }
2212 session_id = pAdapter->sessionId;
2213 cdf_mem_set(&roam_params, sizeof(roam_params), 0);
2214 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2215 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
2216 hddLog(LOGE, FL("attr request id failed"));
2217 goto fail;
2218 }
2219 req_id = nla_get_u32(
2220 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
2221 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id);
2222 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type);
2223 switch (cmd_type) {
2224 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2225 i = 0;
2226 nla_for_each_nested(curr_attr,
2227 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2228 rem) {
2229 if (nla_parse(tb2,
2230 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2231 nla_data(curr_attr), nla_len(curr_attr),
2232 NULL)) {
2233 hddLog(LOGE,
2234 FL("nla_parse failed"));
2235 goto fail;
2236 }
2237 /* Parse and Fetch allowed SSID list*/
2238 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
2239 hddLog(LOGE, FL("attr allowed ssid failed"));
2240 goto fail;
2241 }
2242 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2243 /*
2244 * Upper Layers include a null termination character.
2245 * Check for the actual permissible length of SSID and
2246 * also ensure not to copy the NULL termination
2247 * character to the driver buffer.
2248 */
2249 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2250 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2251 nla_memcpy(
2252 roam_params.ssid_allowed_list[i].ssId,
2253 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2254 buf_len - 1);
2255 roam_params.ssid_allowed_list[i].length =
2256 buf_len - 1;
2257 hddLog(CDF_TRACE_LEVEL_DEBUG,
2258 FL("SSID[%d]: %.*s,length = %d"), i,
2259 roam_params.ssid_allowed_list[i].length,
2260 roam_params.ssid_allowed_list[i].ssId,
2261 roam_params.ssid_allowed_list[i].length);
2262 i++;
2263 } else {
2264 hddLog(LOGE, FL("Invalid buffer length"));
2265 }
2266 }
2267 roam_params.num_ssid_allowed_list = i;
2268 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"),
2269 roam_params.num_ssid_allowed_list);
2270 sme_update_roam_params(pHddCtx->hHal, session_id,
2271 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2272 break;
2273 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2274 /* Parse and fetch 5G Boost Threshold */
2275 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
2276 hddLog(LOGE, FL("5G boost threshold failed"));
2277 goto fail;
2278 }
2279 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2280 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
2281 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Boost Threshold (%d)"),
2282 roam_params.raise_rssi_thresh_5g);
2283 /* Parse and fetch 5G Penalty Threshold */
2284 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
2285 hddLog(LOGE, FL("5G penalty threshold failed"));
2286 goto fail;
2287 }
2288 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2289 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
2290 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Penalty Threshold (%d)"),
2291 roam_params.drop_rssi_thresh_5g);
2292 /* Parse and fetch 5G Boost Factor */
2293 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
2294 hddLog(LOGE, FL("5G boost Factor failed"));
2295 goto fail;
2296 }
2297 roam_params.raise_factor_5g = nla_get_u32(
2298 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
2299 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"),
2300 roam_params.raise_factor_5g);
2301 /* Parse and fetch 5G Penalty factor */
2302 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
2303 hddLog(LOGE, FL("5G Penalty Factor failed"));
2304 goto fail;
2305 }
2306 roam_params.drop_factor_5g = nla_get_u32(
2307 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
2308 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Penalty factor (%d)"),
2309 roam_params.drop_factor_5g);
2310 /* Parse and fetch 5G Max Boost */
2311 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
2312 hddLog(LOGE, FL("5G Max Boost failed"));
2313 goto fail;
2314 }
2315 roam_params.max_raise_rssi_5g = nla_get_u32(
2316 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
2317 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"),
2318 roam_params.max_raise_rssi_5g);
2319 /* Parse and fetch Rssi Diff */
2320 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
2321 hddLog(LOGE, FL("Rssi Diff failed"));
2322 goto fail;
2323 }
2324 roam_params.rssi_diff = nla_get_s32(
2325 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
2326 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"),
2327 roam_params.rssi_diff);
2328 /* Parse and fetch Alert Rssi Threshold */
2329 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
2330 hddLog(LOGE, FL("Alert Rssi Threshold failed"));
2331 goto fail;
2332 }
2333 roam_params.alert_rssi_threshold = nla_get_u32(
2334 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
2335 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Alert RSSI Threshold (%d)"),
2336 roam_params.alert_rssi_threshold);
2337 sme_update_roam_params(pHddCtx->hHal, session_id,
2338 roam_params,
2339 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2340 break;
2341 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2342 /* Parse and fetch Activate Good Rssi Roam */
2343 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
2344 hddLog(LOGE, FL("Activate Good Rssi Roam failed"));
2345 goto fail;
2346 }
2347 roam_params.good_rssi_roam = nla_get_s32(
2348 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
2349 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Activate Good Rssi Roam (%d)"),
2350 roam_params.good_rssi_roam);
2351 sme_update_roam_params(pHddCtx->hHal, session_id,
2352 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2353 break;
2354 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2355 /* Parse and fetch number of preferred BSSID */
2356 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
2357 hddLog(LOGE, FL("attr num of preferred bssid failed"));
2358 goto fail;
2359 }
2360 roam_params.num_bssid_favored = nla_get_u32(
2361 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
2362 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Num of Preferred BSSID (%d)"),
2363 roam_params.num_bssid_favored);
2364 i = 0;
2365 nla_for_each_nested(curr_attr,
2366 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2367 rem) {
2368 if (nla_parse(tb2,
2369 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2370 nla_data(curr_attr), nla_len(curr_attr),
2371 NULL)) {
2372 hddLog(LOGE, FL("nla_parse failed"));
2373 goto fail;
2374 }
2375 /* Parse and fetch MAC address */
2376 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
2377 hddLog(LOGE, FL("attr mac address failed"));
2378 goto fail;
2379 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002380 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302382 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002383 hdd_debug(MAC_ADDRESS_STR,
2384 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 /* Parse and fetch preference factor*/
2386 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
2387 hddLog(LOGE, FL("BSSID Preference score failed"));
2388 goto fail;
2389 }
2390 roam_params.bssid_favored_factor[i] = nla_get_u32(
2391 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
2392 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("BSSID Preference score (%d)"),
2393 roam_params.bssid_favored_factor[i]);
2394 i++;
2395 }
2396 sme_update_roam_params(pHddCtx->hHal, session_id,
2397 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2398 break;
2399 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2400 /* Parse and fetch number of blacklist BSSID */
2401 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
2402 hddLog(LOGE, FL("attr num of blacklist bssid failed"));
2403 goto fail;
2404 }
2405 roam_params.num_bssid_avoid_list = nla_get_u32(
2406 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
2407 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Num of blacklist BSSID (%d)"),
2408 roam_params.num_bssid_avoid_list);
2409 i = 0;
2410 nla_for_each_nested(curr_attr,
2411 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2412 rem) {
2413 if (nla_parse(tb2,
2414 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2415 nla_data(curr_attr), nla_len(curr_attr),
2416 NULL)) {
2417 hddLog(LOGE, FL("nla_parse failed"));
2418 goto fail;
2419 }
2420 /* Parse and fetch MAC address */
2421 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
2422 hddLog(LOGE, FL("attr blacklist addr failed"));
2423 goto fail;
2424 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002425 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302427 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002428 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002430 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 i++;
2432 }
2433 sme_update_roam_params(pHddCtx->hHal, session_id,
2434 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2435 break;
2436 }
2437 return 0;
2438fail:
2439 return -EINVAL;
2440}
2441
2442/**
2443 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2444 * @wiphy: pointer to wireless wiphy structure.
2445 * @wdev: pointer to wireless_dev structure.
2446 * @data: Pointer to the data to be passed via vendor interface
2447 * @data_len:Length of the data to be passed
2448 *
2449 * Return: Return the Success or Failure code.
2450 */
2451static int
2452wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2453 struct wireless_dev *wdev,
2454 const void *data,
2455 int data_len)
2456{
2457 int ret;
2458
2459 cds_ssr_protect(__func__);
2460 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2461 data, data_len);
2462 cds_ssr_unprotect(__func__);
2463
2464 return ret;
2465}
2466
2467static const struct nla_policy
2468wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2469 +1] = {
2470 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2471};
2472
2473/**
2474 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2475 * @hdd_ctx: HDD context
2476 * @device_mode: device mode
2477 * Return: bool
2478 */
2479static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
2480 device_mode_t device_mode)
2481{
2482 hdd_adapter_t *adapter;
2483 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2484 hdd_ap_ctx_t *ap_ctx;
2485 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302486 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302488 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 &adapter_node);
2490
2491 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302492 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 adapter = adapter_node->pAdapter;
2494
2495 if ((device_mode == adapter->device_mode) &&
2496 (device_mode == WLAN_HDD_SOFTAP)) {
2497 ap_ctx =
2498 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2499
2500 /*
2501 * if there is SAP already running on DFS channel,
2502 * do not disable scan on dfs channels. Note that
2503 * with SAP on DFS, there cannot be conurrency on
2504 * single radio. But then we can have multiple
2505 * radios !!
2506 */
2507 if (CHANNEL_STATE_DFS ==
2508 cds_get_channel_state(
2509 ap_ctx->operatingChannel)) {
2510 hddLog(CDF_TRACE_LEVEL_ERROR,
2511 FL("SAP running on DFS channel"));
2512 return true;
2513 }
2514 }
2515
2516 if ((device_mode == adapter->device_mode) &&
2517 (device_mode == WLAN_HDD_INFRA_STATION)) {
2518 sta_ctx =
2519 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2520
2521 /*
2522 * if STA is already connected on DFS channel,
2523 * do not disable scan on dfs channels
2524 */
2525 if (hdd_conn_is_connected(sta_ctx) &&
2526 (CHANNEL_STATE_DFS ==
2527 cds_get_channel_state(
2528 sta_ctx->conn_info.operationChannel))) {
2529 hddLog(LOGE,
2530 FL("client connected on DFS channel"));
2531 return true;
2532 }
2533 }
2534
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302535 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 adapter_node,
2537 &next);
2538 adapter_node = next;
2539 }
2540
2541 return false;
2542}
2543
2544/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002545 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2546 * @hdd_ctx: HDD context within host driver
2547 * @adapter: Adapter pointer
2548 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2549 *
2550 * Loops through devices to see who is operating on DFS channels
2551 * and then disables/enables DFS channels by calling SME API.
2552 * Fails the disable request if any device is active on a DFS channel.
2553 *
2554 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002556
2557int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2558 hdd_adapter_t *adapter,
2559 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302562 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564
2565 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2566 if (no_dfs_flag) {
2567 status = wlan_hdd_check_dfs_channel_for_adapter(
2568 hdd_ctx, WLAN_HDD_INFRA_STATION);
2569
2570 if (true == status)
2571 return -EOPNOTSUPP;
2572
2573 status = wlan_hdd_check_dfs_channel_for_adapter(
2574 hdd_ctx, WLAN_HDD_SOFTAP);
2575
2576 if (true == status)
2577 return -EOPNOTSUPP;
2578 }
2579
2580 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2581
2582 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2583
2584 /*
2585 * call the SME API to tunnel down the new channel list
2586 * to the firmware
2587 */
2588 status = sme_handle_dfs_chan_scan(
2589 h_hal, hdd_ctx->config->enableDFSChnlScan);
2590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302591 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002592 ret_val = 0;
2593
2594 /*
2595 * Clear the SME scan cache also. Note that the
2596 * clearing of scan results is independent of session;
2597 * so no need to iterate over
2598 * all sessions
2599 */
2600 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302601 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 ret_val = -EPERM;
2603 }
2604
2605 } else {
2606 hddLog(CDF_TRACE_LEVEL_INFO,
2607 FL(" the DFS flag has not changed"));
2608 ret_val = 0;
2609 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002610 return ret_val;
2611}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002613/**
2614 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2615 * @wiphy: corestack handler
2616 * @wdev: wireless device
2617 * @data: data
2618 * @data_len: data length
2619 * Return: success(0) or reason code for failure
2620 */
2621static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2622 struct wireless_dev *wdev,
2623 const void *data,
2624 int data_len)
2625{
2626 struct net_device *dev = wdev->netdev;
2627 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2628 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2629 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2630 int ret_val;
2631 uint32_t no_dfs_flag = 0;
2632
2633 ENTER();
2634 ret_val = wlan_hdd_validate_context(hdd_ctx);
2635
2636 if (ret_val) {
2637 hdd_err("HDD context is not valid");
2638 return ret_val;
2639 }
2640
2641 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2642 data, data_len,
2643 wlan_hdd_set_no_dfs_flag_config_policy)) {
2644 hdd_err("invalid attr");
2645 return -EINVAL;
2646 }
2647
2648 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2649 hdd_err("attr dfs flag failed");
2650 return -EINVAL;
2651 }
2652
2653 no_dfs_flag = nla_get_u32(
2654 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2655
2656 hddLog(LOG1, FL(" DFS flag = %d"), no_dfs_flag);
2657
2658 if (no_dfs_flag > 1) {
2659 hddLog(LOGE, FL("invalid value of dfs flag"));
2660 return -EINVAL;
2661 }
2662
2663 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2664 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665 return ret_val;
2666}
2667
2668/**
2669 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2670 *
2671 * @wiphy: wiphy device pointer
2672 * @wdev: wireless device pointer
2673 * @data: Vendof command data buffer
2674 * @data_len: Buffer length
2675 *
2676 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2677 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2678 *
2679 * Return: EOK or other error codes.
2680 */
2681
2682static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2683 struct wireless_dev *wdev,
2684 const void *data,
2685 int data_len)
2686{
2687 int ret;
2688
2689 cds_ssr_protect(__func__);
2690 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2691 data, data_len);
2692 cds_ssr_unprotect(__func__);
2693
2694 return ret;
2695}
2696
2697#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2698/**
2699 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2700 * @wiphy: pointer to wireless wiphy structure.
2701 * @wdev: pointer to wireless_dev structure.
2702 * @data: Pointer to the Key data
2703 * @data_len:Length of the data passed
2704 *
2705 * This is called when wlan driver needs to save the keys received via
2706 * vendor specific command.
2707 *
2708 * Return: Return the Success or Failure code.
2709 */
2710static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2711 struct wireless_dev *wdev,
2712 const void *data, int data_len)
2713{
2714 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
2715 struct net_device *dev = wdev->netdev;
2716 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
2717 hdd_context_t *hdd_ctx_ptr;
2718 int status;
2719
Anurag Chouhan6d760662016-02-20 16:05:43 +05302720 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 hdd_err("Command not allowed in FTM mode");
2722 return -EPERM;
2723 }
2724
2725 if ((data == NULL) || (data_len == 0) ||
2726 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
2727 hddLog(LOGE, FL("Invalid data"));
2728 return -EINVAL;
2729 }
2730
2731 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
2732 if (!hdd_ctx_ptr) {
2733 hddLog(LOGE, FL("HDD context is null"));
2734 return -EINVAL;
2735 }
2736
2737 status = wlan_hdd_validate_context(hdd_ctx_ptr);
2738 if (0 != status) {
2739 hddLog(LOGE, FL("HDD context is invalid"));
2740 return status;
2741 }
2742 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
2743 hdd_adapter_ptr->sessionId,
2744 true);
2745 cdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
2746 cdf_mem_copy(local_pmk, data, data_len);
2747 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
2748 hdd_adapter_ptr->sessionId, local_pmk, data_len);
2749 return 0;
2750}
2751
2752/**
2753 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2754 * @wiphy: pointer to wireless wiphy structure.
2755 * @wdev: pointer to wireless_dev structure.
2756 * @data: Pointer to the Key data
2757 * @data_len:Length of the data passed
2758 *
2759 * This is called when wlan driver needs to save the keys received via
2760 * vendor specific command.
2761 *
2762 * Return: Return the Success or Failure code.
2763 */
2764static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2765 struct wireless_dev *wdev,
2766 const void *data, int data_len)
2767{
2768 int ret;
2769
2770 cds_ssr_protect(__func__);
2771 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
2772 cds_ssr_unprotect(__func__);
2773
2774 return ret;
2775}
2776
2777static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
2778 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
2779 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
2780 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
2781};
2782
2783/**
2784 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2785 * @wiphy: pointer to wireless wiphy structure.
2786 * @wdev: pointer to wireless_dev structure.
2787 * @data: Pointer to the data to be passed via vendor interface
2788 * @data_len:Length of the data to be passed
2789 *
2790 * This is called when wlan driver needs to send wifi driver related info
2791 * (driver/fw version) to the user space application upon request.
2792 *
2793 * Return: Return the Success or Failure code.
2794 */
2795static int
2796__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2797 struct wireless_dev *wdev,
2798 const void *data, int data_len)
2799{
2800 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2801 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
2802 tSirVersionString version;
2803 uint32_t version_len;
2804 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
2805 uint8_t attr;
2806 int status;
2807 struct sk_buff *reply_skb = NULL;
2808
Anurag Chouhan6d760662016-02-20 16:05:43 +05302809 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 hdd_err("Command not allowed in FTM mode");
2811 return -EPERM;
2812 }
2813
2814 status = wlan_hdd_validate_context(hdd_ctx);
2815 if (0 != status) {
2816 hddLog(LOGE, FL("HDD context is not valid"));
2817 return -EINVAL;
2818 }
2819
2820 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
2821 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
2822 hddLog(LOGE, FL("WIFI_INFO_GET NL CMD parsing failed"));
2823 return -EINVAL;
2824 }
2825
2826 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
2827 hddLog(LOG1, FL("Rcvd req for Driver version"));
2828 strlcpy(version, QWLAN_VERSIONSTR, sizeof(version));
2829 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
2830 } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
2831 hddLog(LOG1, FL("Rcvd req for FW version"));
2832 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
2833 &crmid);
2834 snprintf(version, sizeof(version), "%d:%d:%d:%d",
2835 major_spid, minor_spid, siid, crmid);
2836 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
2837 } else {
2838 hddLog(LOGE, FL("Invalid attribute in get wifi info request"));
2839 return -EINVAL;
2840 }
2841
2842 version_len = strlen(version);
2843 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2844 version_len + NLA_HDRLEN + NLMSG_HDRLEN);
2845 if (!reply_skb) {
2846 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2847 return -ENOMEM;
2848 }
2849
2850 if (nla_put(reply_skb, attr, version_len, version)) {
2851 hddLog(LOGE, FL("nla put fail"));
2852 kfree_skb(reply_skb);
2853 return -EINVAL;
2854 }
2855
2856 return cfg80211_vendor_cmd_reply(reply_skb);
2857}
2858
2859/**
2860 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2861 * @wiphy: pointer to wireless wiphy structure.
2862 * @wdev: pointer to wireless_dev structure.
2863 * @data: Pointer to the data to be passed via vendor interface
2864 * @data_len:Length of the data to be passed
2865 *
2866 * This is called when wlan driver needs to send wifi driver related info
2867 * (driver/fw version) to the user space application upon request.
2868 *
2869 * Return: Return the Success or Failure code.
2870 */
2871static int
2872wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2873 struct wireless_dev *wdev,
2874 const void *data, int data_len)
2875{
2876 int ret;
2877
2878 cds_ssr_protect(__func__);
2879 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
2880 cds_ssr_unprotect(__func__);
2881
2882 return ret;
2883}
2884
2885/**
2886 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
2887 * @wiphy: pointer to wireless wiphy structure.
2888 * @wdev: pointer to wireless_dev structure.
2889 * @data: Pointer to the data to be passed via vendor interface
2890 * @data_len:Length of the data to be passed
2891 *
2892 * This is called by userspace to know the supported logger features
2893 *
2894 * Return: Return the Success or Failure code.
2895 */
2896static int
2897__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
2898 struct wireless_dev *wdev,
2899 const void *data, int data_len)
2900{
2901 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2902 int status;
2903 uint32_t features;
2904 struct sk_buff *reply_skb = NULL;
2905
Anurag Chouhan6d760662016-02-20 16:05:43 +05302906 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 hdd_err("Command not allowed in FTM mode");
2908 return -EPERM;
2909 }
2910
2911 status = wlan_hdd_validate_context(hdd_ctx);
2912 if (0 != status) {
2913 hddLog(LOGE, FL("HDD context is not valid"));
2914 return -EINVAL;
2915 }
2916
2917 features = 0;
2918
2919 if (hdd_is_memdump_supported())
2920 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
2921 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
2922 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
2923 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
2924
2925 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2926 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
2927 if (!reply_skb) {
2928 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2929 return -ENOMEM;
2930 }
2931
2932 hddLog(LOG1, FL("Supported logger features: 0x%0x"), features);
2933 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
2934 features)) {
2935 hddLog(LOGE, FL("nla put fail"));
2936 kfree_skb(reply_skb);
2937 return -EINVAL;
2938 }
2939
2940 return cfg80211_vendor_cmd_reply(reply_skb);
2941}
2942
2943/**
2944 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
2945 * @wiphy: pointer to wireless wiphy structure.
2946 * @wdev: pointer to wireless_dev structure.
2947 * @data: Pointer to the data to be passed via vendor interface
2948 * @data_len:Length of the data to be passed
2949 *
2950 * This is called by userspace to know the supported logger features
2951 *
2952 * Return: Return the Success or Failure code.
2953 */
2954static int
2955wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
2956 struct wireless_dev *wdev,
2957 const void *data, int data_len)
2958{
2959 int ret;
2960
2961 cds_ssr_protect(__func__);
2962 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
2963 data, data_len);
2964 cds_ssr_unprotect(__func__);
2965
2966 return ret;
2967}
2968
2969/**
2970 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
2971 * @hdd_ctx_ptr: pointer to HDD Context.
2972 * @bssid: pointer to bssid of roamed AP.
2973 * @req_rsn_ie: Pointer to request RSN IE
2974 * @req_rsn_len: Length of the request RSN IE
2975 * @rsp_rsn_ie: Pointer to response RSN IE
2976 * @rsp_rsn_len: Length of the response RSN IE
2977 * @roam_info_ptr: Pointer to the roaming related information
2978 *
2979 * This is called when wlan driver needs to send the roaming and
2980 * authorization information after roaming.
2981 *
2982 * The information that would be sent is the request RSN IE, response
2983 * RSN IE and BSSID of the newly roamed AP.
2984 *
2985 * If the Authorized status is authenticated, then additional parameters
2986 * like PTK's KCK and KEK and Replay Counter would also be passed to the
2987 * supplicant.
2988 *
2989 * The supplicant upon receiving this event would ignore the legacy
2990 * cfg80211_roamed call and use the entire information from this event.
2991 * The cfg80211_roamed should still co-exist since the kernel will
2992 * make use of the parameters even if the supplicant ignores it.
2993 *
2994 * Return: Return the Success or Failure code.
2995 */
2996int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
2997 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
2998 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
2999{
3000 struct sk_buff *skb = NULL;
3001 ENTER();
3002
3003 if (wlan_hdd_validate_context(hdd_ctx_ptr)) {
3004 hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid "));
3005 return -EINVAL;
3006 }
3007
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003008 if (!hdd_ctx_ptr->config->isRoamOffloadEnabled ||
3009 !roam_info_ptr->roamSynchInProgress)
3010 return 0;
3011
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003012 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3013 NULL,
3014 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3015 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3016 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003017 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3019 GFP_KERNEL);
3020
3021 if (!skb) {
3022 hddLog(CDF_TRACE_LEVEL_ERROR,
3023 FL("cfg80211_vendor_event_alloc failed"));
3024 return -EINVAL;
3025 }
3026
3027 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3028 ETH_ALEN, bssid) ||
3029 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3030 req_rsn_len, req_rsn_ie) ||
3031 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3032 rsp_rsn_len, rsp_rsn_ie)) {
3033 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
3034 goto nla_put_failure;
3035 }
3036 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"),
3037 roam_info_ptr->synchAuthStatus);
3038 if (roam_info_ptr->synchAuthStatus ==
3039 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
3040 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's"));
Naveen Rawat14298b92015-11-25 16:27:41 -08003041 if (nla_put_u8(skb,
3042 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3043 hdd_err("nla put fail");
3044 goto nla_put_failure;
3045 }
3046 /* if FT connection: dont send ROAM_AUTH_KEY_REPLAY_CTR */
3047 if (roam_info_ptr->u.pConnectedProfile->AuthType !=
3048 eCSR_AUTH_TYPE_FT_RSN &&
3049 roam_info_ptr->u.pConnectedProfile->AuthType !=
3050 eCSR_AUTH_TYPE_FT_RSN_PSK &&
3051 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3052 SIR_REPLAY_CTR_LEN, roam_info_ptr->replay_ctr)) {
3053 hdd_err("non FT connection.");
3054 hdd_err("failed to send replay counter.");
3055 goto nla_put_failure;
3056 }
3057 if (nla_put(skb,
3058 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3059 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3060 nla_put(skb,
3061 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3062 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3063 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 goto nla_put_failure;
3065 }
3066 } else {
3067 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's"));
3068 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3069 false)) {
3070 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
3071 goto nla_put_failure;
3072 }
3073 }
3074
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003075 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Subnet Change Status = %d"),
3076 roam_info_ptr->subnet_change_status);
3077
3078 /*
3079 * Add subnet change status if subnet has changed
3080 * 0 = unchanged
3081 * 1 = changed
3082 * 2 = unknown
3083 */
3084 if (roam_info_ptr->subnet_change_status) {
3085 if (nla_put_u8(skb,
3086 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3087 roam_info_ptr->subnet_change_status)) {
3088 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
3089 goto nla_put_failure;
3090 }
3091 }
3092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003093 cfg80211_vendor_event(skb, GFP_KERNEL);
3094 return 0;
3095
3096nla_put_failure:
3097 kfree_skb(skb);
3098 return -EINVAL;
3099}
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003100#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003101
3102static const struct nla_policy
3103wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3104
3105 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3106 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3107 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3108};
3109
3110
3111/**
3112 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3113 * vendor command
3114 *
3115 * @wiphy: wiphy device pointer
3116 * @wdev: wireless device pointer
3117 * @data: Vendor command data buffer
3118 * @data_len: Buffer length
3119 *
3120 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3121 *
3122 * Return: Error code.
3123 */
3124static int
3125__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3126 struct wireless_dev *wdev,
3127 const void *data,
3128 int data_len)
3129{
3130 struct net_device *dev = wdev->netdev;
3131 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3132 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3133 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3134 int ret_val = 0;
3135 u32 modulated_dtim;
3136 u16 stats_avg_factor;
3137 u32 guard_time;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303138 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003139
Anurag Chouhan6d760662016-02-20 16:05:43 +05303140 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 hdd_err("Command not allowed in FTM mode");
3142 return -EPERM;
3143 }
3144
3145 ret_val = wlan_hdd_validate_context(hdd_ctx);
3146 if (ret_val) {
3147 hddLog(LOGE, FL("HDD context is not valid"));
3148 return ret_val;
3149 }
3150
3151 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3152 data, data_len,
3153 wlan_hdd_wifi_config_policy)) {
3154 hddLog(LOGE, FL("invalid attr"));
3155 return -EINVAL;
3156 }
3157
3158 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3159 modulated_dtim = nla_get_u32(
3160 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3161
3162 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3163 adapter->sessionId,
3164 modulated_dtim);
3165
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303166 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 ret_val = -EPERM;
3168 }
3169
3170 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3171 stats_avg_factor = nla_get_u16(
3172 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3173 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3174 adapter->sessionId,
3175 stats_avg_factor);
3176
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303177 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 ret_val = -EPERM;
3179 }
3180
3181
3182 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3183 guard_time = nla_get_u32(
3184 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3185 status = sme_configure_guard_time(hdd_ctx->hHal,
3186 adapter->sessionId,
3187 guard_time);
3188
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303189 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 ret_val = -EPERM;
3191 }
3192
3193 return ret_val;
3194}
3195
3196/**
3197 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3198 * vendor command
3199 *
3200 * @wiphy: wiphy device pointer
3201 * @wdev: wireless device pointer
3202 * @data: Vendor command data buffer
3203 * @data_len: Buffer length
3204 *
3205 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3206 *
3207 * Return: EOK or other error codes.
3208 */
3209static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3210 struct wireless_dev *wdev,
3211 const void *data,
3212 int data_len)
3213{
3214 int ret;
3215
3216 cds_ssr_protect(__func__);
3217 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3218 data, data_len);
3219 cds_ssr_unprotect(__func__);
3220
3221 return ret;
3222}
3223
3224static const struct
3225nla_policy
3226qca_wlan_vendor_wifi_logger_start_policy
3227[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3228 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3229 = {.type = NLA_U32 },
3230 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3231 = {.type = NLA_U32 },
3232 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3233 = {.type = NLA_U32 },
3234};
3235
3236/**
3237 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3238 * or disable the collection of packet statistics from the firmware
3239 * @wiphy: WIPHY structure pointer
3240 * @wdev: Wireless device structure pointer
3241 * @data: Pointer to the data received
3242 * @data_len: Length of the data received
3243 *
3244 * This function enables or disables the collection of packet statistics from
3245 * the firmware
3246 *
3247 * Return: 0 on success and errno on failure
3248 */
3249static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3250 struct wireless_dev *wdev,
3251 const void *data,
3252 int data_len)
3253{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303254 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3256 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
3257 struct sir_wifi_start_log start_log;
3258
Anurag Chouhan6d760662016-02-20 16:05:43 +05303259 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 hdd_err("Command not allowed in FTM mode");
3261 return -EPERM;
3262 }
3263
3264 status = wlan_hdd_validate_context(hdd_ctx);
3265 if (0 != status) {
3266 hddLog(LOGE, FL("HDD context is not valid"));
3267 return -EINVAL;
3268 }
3269
3270 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
3271 data, data_len,
3272 qca_wlan_vendor_wifi_logger_start_policy)) {
3273 hddLog(LOGE, FL("Invalid attribute"));
3274 return -EINVAL;
3275 }
3276
3277 /* Parse and fetch ring id */
3278 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
3279 hddLog(LOGE, FL("attr ATTR failed"));
3280 return -EINVAL;
3281 }
3282 start_log.ring_id = nla_get_u32(
3283 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003284 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285
3286 /* Parse and fetch verbose level */
3287 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
3288 hddLog(LOGE, FL("attr verbose_level failed"));
3289 return -EINVAL;
3290 }
3291 start_log.verbose_level = nla_get_u32(
3292 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003293 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294
3295 /* Parse and fetch flag */
3296 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
3297 hddLog(LOGE, FL("attr flag failed"));
3298 return -EINVAL;
3299 }
3300 start_log.flag = nla_get_u32(
3301 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003302 hdd_info("flag=%d", start_log.flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303
3304 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
3305
3306 if (start_log.ring_id == RING_ID_WAKELOCK) {
3307 /* Start/stop wakelock events */
3308 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
3309 cds_set_wakelock_logging(true);
3310 else
3311 cds_set_wakelock_logging(false);
3312 return 0;
3313 }
3314
3315 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"),
3318 status);
3319 return -EINVAL;
3320 }
3321 return 0;
3322}
3323
3324/**
3325 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
3326 * or disable the collection of packet statistics from the firmware
3327 * @wiphy: WIPHY structure pointer
3328 * @wdev: Wireless device structure pointer
3329 * @data: Pointer to the data received
3330 * @data_len: Length of the data received
3331 *
3332 * This function is used to enable or disable the collection of packet
3333 * statistics from the firmware
3334 *
3335 * Return: 0 on success and errno on failure
3336 */
3337static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3338 struct wireless_dev *wdev,
3339 const void *data,
3340 int data_len)
3341{
3342 int ret = 0;
3343
3344 cds_ssr_protect(__func__);
3345 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
3346 wdev, data, data_len);
3347 cds_ssr_unprotect(__func__);
3348
3349 return ret;
3350}
3351
3352static const struct
3353nla_policy
3354qca_wlan_vendor_wifi_logger_get_ring_data_policy
3355[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
3356 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
3357 = {.type = NLA_U32 },
3358};
3359
3360/**
3361 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
3362 * @wiphy: WIPHY structure pointer
3363 * @wdev: Wireless device structure pointer
3364 * @data: Pointer to the data received
3365 * @data_len: Length of the data received
3366 *
3367 * This function is used to flush or retrieve the per packet statistics from
3368 * the driver
3369 *
3370 * Return: 0 on success and errno on failure
3371 */
3372static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3373 struct wireless_dev *wdev,
3374 const void *data,
3375 int data_len)
3376{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303377 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003378 uint32_t ring_id;
3379 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3380 struct nlattr *tb
3381 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
3382
Anurag Chouhan6d760662016-02-20 16:05:43 +05303383 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384 hdd_err("Command not allowed in FTM mode");
3385 return -EPERM;
3386 }
3387
3388 status = wlan_hdd_validate_context(hdd_ctx);
3389 if (0 != status) {
3390 hddLog(LOGE, FL("HDD context is not valid"));
3391 return -EINVAL;
3392 }
3393
3394 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
3395 data, data_len,
3396 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
3397 hddLog(LOGE, FL("Invalid attribute"));
3398 return -EINVAL;
3399 }
3400
3401 /* Parse and fetch ring id */
3402 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
3403 hddLog(LOGE, FL("attr ATTR failed"));
3404 return -EINVAL;
3405 }
3406
3407 ring_id = nla_get_u32(
3408 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
3409
3410 if (ring_id == RING_ID_PER_PACKET_STATS) {
3411 wlan_logging_set_per_pkt_stats();
3412 hddLog(LOG1, FL("Flushing/Retrieving packet stats"));
3413 }
3414
3415 hddLog(LOG1, FL("Bug report triggered by framework"));
3416
3417 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
3418 WLAN_LOG_INDICATOR_FRAMEWORK,
3419 WLAN_LOG_REASON_CODE_UNUSED);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303420 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 hddLog(LOGE, FL("Failed to trigger bug report"));
3422 return -EINVAL;
3423 }
3424
3425 return 0;
3426}
3427
3428/**
3429 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
3430 * @wiphy: WIPHY structure pointer
3431 * @wdev: Wireless device structure pointer
3432 * @data: Pointer to the data received
3433 * @data_len: Length of the data received
3434 *
3435 * This function is used to flush or retrieve the per packet statistics from
3436 * the driver
3437 *
3438 * Return: 0 on success and errno on failure
3439 */
3440static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3441 struct wireless_dev *wdev,
3442 const void *data,
3443 int data_len)
3444{
3445 int ret = 0;
3446
3447 cds_ssr_protect(__func__);
3448 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
3449 wdev, data, data_len);
3450 cds_ssr_unprotect(__func__);
3451
3452 return ret;
3453}
3454
3455#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
3456/**
3457 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
3458 * @hdd_ctx: HDD context
3459 * @request_id: [input] request id
3460 * @pattern_id: [output] pattern id
3461 *
3462 * This function loops through request id to pattern id array
3463 * if the slot is available, store the request id and return pattern id
3464 * if entry exists, return the pattern id
3465 *
3466 * Return: 0 on success and errno on failure
3467 */
3468static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3469 uint32_t request_id,
3470 uint8_t *pattern_id)
3471{
3472 uint32_t i;
3473
3474 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3475 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3476 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
3477 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
3478 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3479 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3480 return 0;
3481 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
3482 request_id) {
3483 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3484 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3485 return 0;
3486 }
3487 }
3488 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3489 return -EINVAL;
3490}
3491
3492/**
3493 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
3494 * @hdd_ctx: HDD context
3495 * @request_id: [input] request id
3496 * @pattern_id: [output] pattern id
3497 *
3498 * This function loops through request id to pattern id array
3499 * reset request id to 0 (slot available again) and
3500 * return pattern id
3501 *
3502 * Return: 0 on success and errno on failure
3503 */
3504static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3505 uint32_t request_id,
3506 uint8_t *pattern_id)
3507{
3508 uint32_t i;
3509
3510 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3511 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3512 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
3513 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
3514 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3515 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3516 return 0;
3517 }
3518 }
3519 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3520 return -EINVAL;
3521}
3522
3523
3524/*
3525 * define short names for the global vendor params
3526 * used by __wlan_hdd_cfg80211_offloaded_packets()
3527 */
3528#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
3529#define PARAM_REQUEST_ID \
3530 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
3531#define PARAM_CONTROL \
3532 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
3533#define PARAM_IP_PACKET \
3534 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
3535#define PARAM_SRC_MAC_ADDR \
3536 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
3537#define PARAM_DST_MAC_ADDR \
3538 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
3539#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
3540
3541/**
3542 * wlan_hdd_add_tx_ptrn() - add tx pattern
3543 * @adapter: adapter pointer
3544 * @hdd_ctx: hdd context
3545 * @tb: nl attributes
3546 *
3547 * This function reads the NL attributes and forms a AddTxPtrn message
3548 * posts it to SME.
3549 *
3550 */
3551static int
3552wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3553 struct nlattr **tb)
3554{
3555 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303556 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 uint32_t request_id, ret, len;
3558 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303559 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003560 uint16_t eth_type = htons(ETH_P_IP);
3561
3562 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3563 hddLog(LOGE, FL("Not in Connected state!"));
3564 return -ENOTSUPP;
3565 }
3566
3567 add_req = cdf_mem_malloc(sizeof(*add_req));
3568 if (!add_req) {
3569 hddLog(LOGE, FL("memory allocation failed"));
3570 return -ENOMEM;
3571 }
3572
3573 /* Parse and fetch request Id */
3574 if (!tb[PARAM_REQUEST_ID]) {
3575 hddLog(LOGE, FL("attr request id failed"));
3576 goto fail;
3577 }
3578
3579 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3580 if (request_id == MAX_REQUEST_ID) {
3581 hddLog(LOGE, FL("request_id cannot be MAX"));
3582 return -EINVAL;
3583 }
3584 hddLog(LOG1, FL("Request Id: %u"), request_id);
3585
3586 if (!tb[PARAM_PERIOD]) {
3587 hddLog(LOGE, FL("attr period failed"));
3588 goto fail;
3589 }
3590 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
3591 hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs);
3592 if (add_req->usPtrnIntervalMs == 0) {
3593 hddLog(LOGE, FL("Invalid interval zero, return failure"));
3594 goto fail;
3595 }
3596
3597 if (!tb[PARAM_SRC_MAC_ADDR]) {
3598 hddLog(LOGE, FL("attr source mac address failed"));
3599 goto fail;
3600 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08003601 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303602 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003603 hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003604 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605
Srinivas Girigowda31896552015-11-18 22:59:52 -08003606 if (!cdf_is_macaddr_equal(&add_req->mac_address,
3607 &adapter->macAddressCurrent)) {
3608 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 goto fail;
3610 }
3611
3612 if (!tb[PARAM_DST_MAC_ADDR]) {
3613 hddLog(LOGE, FL("attr dst mac address failed"));
3614 goto fail;
3615 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303616 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617 hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR,
3618 MAC_ADDR_ARRAY(dst_addr.bytes));
3619
3620 if (!tb[PARAM_IP_PACKET]) {
3621 hddLog(LOGE, FL("attr ip packet failed"));
3622 goto fail;
3623 }
3624 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
3625 hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize);
3626
3627 if (add_req->ucPtrnSize < 0 ||
3628 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
3629 ETH_HLEN)) {
3630 hddLog(LOGE, FL("Invalid IP packet len: %d"),
3631 add_req->ucPtrnSize);
3632 goto fail;
3633 }
3634
3635 len = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303636 cdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
3637 len += QDF_MAC_ADDR_SIZE;
Srinivas Girigowda31896552015-11-18 22:59:52 -08003638 cdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303639 QDF_MAC_ADDR_SIZE);
3640 len += QDF_MAC_ADDR_SIZE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003641 cdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
3642 len += 2;
3643
3644 /*
3645 * This is the IP packet, add 14 bytes Ethernet (802.3) header
3646 * ------------------------------------------------------------
3647 * | 14 bytes Ethernet (802.3) header | IP header and payload |
3648 * ------------------------------------------------------------
3649 */
3650 cdf_mem_copy(&add_req->ucPattern[len],
3651 nla_data(tb[PARAM_IP_PACKET]),
3652 add_req->ucPtrnSize);
3653 add_req->ucPtrnSize += len;
3654
3655 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3656 if (ret) {
3657 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3658 goto fail;
3659 }
3660 add_req->ucPtrnId = pattern_id;
3661 hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId);
3662
3663 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303664 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 hddLog(LOGE,
3666 FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status);
3667 goto fail;
3668 }
3669
3670 EXIT();
3671 cdf_mem_free(add_req);
3672 return 0;
3673
3674fail:
3675 cdf_mem_free(add_req);
3676 return -EINVAL;
3677}
3678
3679/**
3680 * wlan_hdd_del_tx_ptrn() - delete tx pattern
3681 * @adapter: adapter pointer
3682 * @hdd_ctx: hdd context
3683 * @tb: nl attributes
3684 *
3685 * This function reads the NL attributes and forms a DelTxPtrn message
3686 * posts it to SME.
3687 *
3688 */
3689static int
3690wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3691 struct nlattr **tb)
3692{
3693 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303694 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695 uint32_t request_id, ret;
3696 uint8_t pattern_id = 0;
3697
3698 /* Parse and fetch request Id */
3699 if (!tb[PARAM_REQUEST_ID]) {
3700 hddLog(LOGE, FL("attr request id failed"));
3701 return -EINVAL;
3702 }
3703 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3704 if (request_id == MAX_REQUEST_ID) {
3705 hddLog(LOGE, FL("request_id cannot be MAX"));
3706 return -EINVAL;
3707 }
3708
3709 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3710 if (ret) {
3711 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3712 return -EINVAL;
3713 }
3714
3715 del_req = cdf_mem_malloc(sizeof(*del_req));
3716 if (!del_req) {
3717 hddLog(LOGE, FL("memory allocation failed"));
3718 return -ENOMEM;
3719 }
3720
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08003721 cdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
3722 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 del_req->ucPtrnId = pattern_id;
3724 hddLog(LOG1, FL("Request Id: %u Pattern id: %d"),
3725 request_id, del_req->ucPtrnId);
3726
3727 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303728 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729 hddLog(LOGE,
3730 FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status);
3731 goto fail;
3732 }
3733
3734 EXIT();
3735 cdf_mem_free(del_req);
3736 return 0;
3737
3738fail:
3739 cdf_mem_free(del_req);
3740 return -EINVAL;
3741}
3742
3743
3744/**
3745 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
3746 * @wiphy: Pointer to wireless phy
3747 * @wdev: Pointer to wireless device
3748 * @data: Pointer to data
3749 * @data_len: Data length
3750 *
3751 * Return: 0 on success, negative errno on failure
3752 */
3753static int
3754__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3755 struct wireless_dev *wdev,
3756 const void *data,
3757 int data_len)
3758{
3759 struct net_device *dev = wdev->netdev;
3760 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3761 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3762 struct nlattr *tb[PARAM_MAX + 1];
3763 uint8_t control;
3764 int ret;
3765 static const struct nla_policy policy[PARAM_MAX + 1] = {
3766 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3767 [PARAM_CONTROL] = { .type = NLA_U32 },
3768 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303769 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303771 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772 [PARAM_PERIOD] = { .type = NLA_U32 },
3773 };
3774
3775 ENTER();
3776
Anurag Chouhan6d760662016-02-20 16:05:43 +05303777 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 hdd_err("Command not allowed in FTM mode");
3779 return -EPERM;
3780 }
3781
3782 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303783 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003784 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785
3786 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
3787 hddLog(LOGE,
3788 FL("Periodic Tx Pattern Offload feature is not supported in FW!"));
3789 return -ENOTSUPP;
3790 }
3791
3792 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3793 hddLog(LOGE, FL("Invalid ATTR"));
3794 return -EINVAL;
3795 }
3796
3797 if (!tb[PARAM_CONTROL]) {
3798 hddLog(LOGE, FL("attr control failed"));
3799 return -EINVAL;
3800 }
3801 control = nla_get_u32(tb[PARAM_CONTROL]);
3802 hddLog(LOG1, FL("Control: %d"), control);
3803
3804 if (control == WLAN_START_OFFLOADED_PACKETS)
3805 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
3806 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
3807 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
3808 else {
3809 hddLog(LOGE, FL("Invalid control: %d"), control);
3810 return -EINVAL;
3811 }
3812}
3813
3814/*
3815 * done with short names for the global vendor params
3816 * used by __wlan_hdd_cfg80211_offloaded_packets()
3817 */
3818#undef PARAM_MAX
3819#undef PARAM_REQUEST_ID
3820#undef PARAM_CONTROL
3821#undef PARAM_IP_PACKET
3822#undef PARAM_SRC_MAC_ADDR
3823#undef PARAM_DST_MAC_ADDR
3824#undef PARAM_PERIOD
3825
3826/**
3827 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
3828 * @wiphy: wiphy structure pointer
3829 * @wdev: Wireless device structure pointer
3830 * @data: Pointer to the data received
3831 * @data_len: Length of @data
3832 *
3833 * Return: 0 on success; errno on failure
3834 */
3835static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3836 struct wireless_dev *wdev,
3837 const void *data,
3838 int data_len)
3839{
3840 int ret = 0;
3841
3842 cds_ssr_protect(__func__);
3843 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
3844 wdev, data, data_len);
3845 cds_ssr_unprotect(__func__);
3846
3847 return ret;
3848}
3849#endif
3850
3851/*
3852 * define short names for the global vendor params
3853 * used by __wlan_hdd_cfg80211_monitor_rssi()
3854 */
3855#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
3856#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
3857#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
3858#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
3859#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
3860
3861/**
3862 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
3863 * @wiphy: Pointer to wireless phy
3864 * @wdev: Pointer to wireless device
3865 * @data: Pointer to data
3866 * @data_len: Data length
3867 *
3868 * Return: 0 on success, negative errno on failure
3869 */
3870static int
3871__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
3872 struct wireless_dev *wdev,
3873 const void *data,
3874 int data_len)
3875{
3876 struct net_device *dev = wdev->netdev;
3877 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3878 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3879 struct nlattr *tb[PARAM_MAX + 1];
3880 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303881 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 int ret;
3883 uint32_t control;
3884 static const struct nla_policy policy[PARAM_MAX + 1] = {
3885 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3886 [PARAM_CONTROL] = { .type = NLA_U32 },
3887 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
3888 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
3889 };
3890
3891 ENTER();
3892
3893 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303894 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896
3897 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3898 hddLog(LOGE, FL("Not in Connected state!"));
3899 return -ENOTSUPP;
3900 }
3901
3902 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3903 hddLog(LOGE, FL("Invalid ATTR"));
3904 return -EINVAL;
3905 }
3906
3907 if (!tb[PARAM_REQUEST_ID]) {
3908 hddLog(LOGE, FL("attr request id failed"));
3909 return -EINVAL;
3910 }
3911
3912 if (!tb[PARAM_CONTROL]) {
3913 hddLog(LOGE, FL("attr control failed"));
3914 return -EINVAL;
3915 }
3916
3917 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3918 req.session_id = adapter->sessionId;
3919 control = nla_get_u32(tb[PARAM_CONTROL]);
3920
3921 if (control == QCA_WLAN_RSSI_MONITORING_START) {
3922 req.control = true;
3923 if (!tb[PARAM_MIN_RSSI]) {
3924 hddLog(LOGE, FL("attr min rssi failed"));
3925 return -EINVAL;
3926 }
3927
3928 if (!tb[PARAM_MAX_RSSI]) {
3929 hddLog(LOGE, FL("attr max rssi failed"));
3930 return -EINVAL;
3931 }
3932
3933 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
3934 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
3935
3936 if (!(req.min_rssi < req.max_rssi)) {
3937 hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"),
3938 req.min_rssi, req.max_rssi);
3939 return -EINVAL;
3940 }
3941 hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"),
3942 req.min_rssi, req.max_rssi);
3943
3944 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
3945 req.control = false;
3946 else {
3947 hddLog(LOGE, FL("Invalid control cmd: %d"), control);
3948 return -EINVAL;
3949 }
3950 hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"),
3951 req.request_id, req.session_id, req.control);
3952
3953 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303954 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 hddLog(LOGE,
3956 FL("sme_set_rssi_monitoring failed(err=%d)"), status);
3957 return -EINVAL;
3958 }
3959
3960 return 0;
3961}
3962
3963/*
3964 * done with short names for the global vendor params
3965 * used by __wlan_hdd_cfg80211_monitor_rssi()
3966 */
3967#undef PARAM_MAX
3968#undef PARAM_CONTROL
3969#undef PARAM_REQUEST_ID
3970#undef PARAM_MAX_RSSI
3971#undef PARAM_MIN_RSSI
3972
3973/**
3974 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
3975 * @wiphy: wiphy structure pointer
3976 * @wdev: Wireless device structure pointer
3977 * @data: Pointer to the data received
3978 * @data_len: Length of @data
3979 *
3980 * Return: 0 on success; errno on failure
3981 */
3982static int
3983wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
3984 const void *data, int data_len)
3985{
3986 int ret;
3987
3988 cds_ssr_protect(__func__);
3989 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
3990 cds_ssr_unprotect(__func__);
3991
3992 return ret;
3993}
3994
3995/**
3996 * hdd_rssi_threshold_breached() - rssi breached NL event
3997 * @hddctx: HDD context
3998 * @data: rssi breached event data
3999 *
4000 * This function reads the rssi breached event %data and fill in the skb with
4001 * NL attributes and send up the NL event.
4002 *
4003 * Return: none
4004 */
4005void hdd_rssi_threshold_breached(void *hddctx,
4006 struct rssi_breach_event *data)
4007{
4008 hdd_context_t *hdd_ctx = hddctx;
4009 struct sk_buff *skb;
4010
4011 ENTER();
4012
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304013 if (wlan_hdd_validate_context(hdd_ctx))
4014 return;
4015 if (!data) {
4016 hddLog(LOGE, FL("data is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 return;
4018 }
4019
4020 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4021 NULL,
4022 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4023 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4024 GFP_KERNEL);
4025
4026 if (!skb) {
4027 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
4028 return;
4029 }
4030
4031 hddLog(LOG1, "Req Id: %u Current rssi: %d",
4032 data->request_id, data->curr_rssi);
4033 hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR,
4034 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4035
4036 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4037 data->request_id) ||
4038 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4039 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4040 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4041 data->curr_rssi)) {
4042 hddLog(LOGE, FL("nla put fail"));
4043 goto fail;
4044 }
4045
4046 cfg80211_vendor_event(skb, GFP_KERNEL);
4047 return;
4048
4049fail:
4050 kfree_skb(skb);
4051 return;
4052}
4053
4054/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
4055 * @wiphy: Pointer to wireless phy
4056 * @wdev: Pointer to wireless device
4057 * @data: Pointer to data
4058 * @data_len: Data length
4059 *
4060 * This function return the preferred frequency list generated by the policy
4061 * manager.
4062 *
4063 * Return: success or failure code
4064 */
4065static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4066 struct wireless_dev
4067 *wdev, const void *data,
4068 int data_len)
4069{
4070 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4071 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304072 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 uint8_t pcl[MAX_NUM_CHAN];
4074 uint32_t pcl_len = 0;
4075 uint32_t freq_list[MAX_NUM_CHAN];
4076 enum cds_con_mode intf_mode;
4077 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4078 struct sk_buff *reply_skb;
4079
4080 ret = wlan_hdd_validate_context(hdd_ctx);
4081 if (ret)
4082 return -EINVAL;
4083
4084 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4085 data, data_len, NULL)) {
4086 hdd_err("Invalid ATTR");
4087 return -EINVAL;
4088 }
4089
4090 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4091 hdd_err("attr interface type failed");
4092 return -EINVAL;
4093 }
4094
4095 intf_mode = nla_get_u32(tb
4096 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4097
4098 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4099 hdd_err("Invalid interface type");
4100 return -EINVAL;
4101 }
4102
4103 hdd_debug("Userspace requested pref freq list");
4104
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004105 status = cds_get_pcl(intf_mode, pcl, &pcl_len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304106 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107 hdd_err("Get pcl failed");
4108 return -EINVAL;
4109 }
4110
4111 /* convert channel number to frequency */
4112 for (i = 0; i < pcl_len; i++) {
4113 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4114 freq_list[i] =
4115 ieee80211_channel_to_frequency(pcl[i],
4116 IEEE80211_BAND_2GHZ);
4117 else
4118 freq_list[i] =
4119 ieee80211_channel_to_frequency(pcl[i],
4120 IEEE80211_BAND_5GHZ);
4121 }
4122
4123 /* send the freq_list back to supplicant */
4124 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4125 sizeof(u32) *
4126 pcl_len +
4127 NLMSG_HDRLEN);
4128
4129 if (!reply_skb) {
4130 hdd_err("Allocate reply_skb failed");
4131 return -EINVAL;
4132 }
4133
4134 if (nla_put_u32(reply_skb,
4135 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4136 intf_mode) ||
4137 nla_put(reply_skb,
4138 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4139 sizeof(uint32_t) * pcl_len,
4140 freq_list)) {
4141 hdd_err("nla put fail");
4142 kfree_skb(reply_skb);
4143 return -EINVAL;
4144 }
4145
4146 return cfg80211_vendor_cmd_reply(reply_skb);
4147}
4148
4149/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4150 * @wiphy: Pointer to wireless phy
4151 * @wdev: Pointer to wireless device
4152 * @data: Pointer to data
4153 * @data_len: Data length
4154 *
4155 * This function return the preferred frequency list generated by the policy
4156 * manager.
4157 *
4158 * Return: success or failure code
4159 */
4160static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4161 struct wireless_dev
4162 *wdev, const void *data,
4163 int data_len)
4164{
4165 int ret = 0;
4166
4167 cds_ssr_protect(__func__);
4168 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
4169 data, data_len);
4170 cds_ssr_unprotect(__func__);
4171
4172 return ret;
4173}
4174
4175/**
4176 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4177 * @wiphy: Pointer to wireless phy
4178 * @wdev: Pointer to wireless device
4179 * @data: Pointer to data
4180 * @data_len: Data length
4181 *
4182 * Return: 0 on success, negative errno on failure
4183 */
4184static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4185 struct wireless_dev *wdev,
4186 const void *data,
4187 int data_len)
4188{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304189 struct net_device *ndev = wdev->netdev;
4190 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4192 int ret = 0;
4193 enum cds_con_mode intf_mode;
4194 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4195 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196
4197 ret = wlan_hdd_validate_context(hdd_ctx);
4198 if (ret)
4199 return ret;
4200
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
4202 data, data_len, NULL)) {
4203 hdd_err("Invalid ATTR");
4204 return -EINVAL;
4205 }
4206
4207 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
4208 hdd_err("attr interface type failed");
4209 return -EINVAL;
4210 }
4211
4212 intf_mode = nla_get_u32(tb
4213 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
4214
4215 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4216 hdd_err("Invalid interface type");
4217 return -EINVAL;
4218 }
4219
4220 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
4221 hdd_err("attr probable freq failed");
4222 return -EINVAL;
4223 }
4224
4225 channel_hint = cds_freq_to_chan(nla_get_u32(tb
4226 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
4227
4228 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004229 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004230 channel_hint, HW_MODE_20_MHZ)) {
4231 hdd_err("Set channel hint failed due to concurrency check");
4232 return -EINVAL;
4233 }
4234
4235 if (hdd_ctx->config->policy_manager_enabled) {
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05304236 ret = cdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304237 if (!QDF_IS_STATUS_SUCCESS(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004238 hdd_err("clearing event failed");
4239
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304240 ret = cds_current_connections_update(adapter->sessionId,
4241 channel_hint,
4242 CDS_UPDATE_REASON_SET_OPER_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304243 if (QDF_STATUS_E_FAILURE == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244 /* return in the failure case */
4245 hdd_err("ERROR: connections update failed!!");
4246 return -EINVAL;
4247 }
4248
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304249 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004250 /*
4251 * Success is the only case for which we expect hw mode
4252 * change to take place, hence we need to wait.
4253 * For any other return value it should be a pass
4254 * through
4255 */
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05304256 ret = cdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304257 if (!QDF_IS_STATUS_SUCCESS(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258 hdd_err("ERROR: cdf wait for event failed!!");
4259 return -EINVAL;
4260 }
4261
4262 }
4263 }
4264
4265 return 0;
4266}
4267
4268/**
4269 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4270 * @wiphy: Pointer to wireless phy
4271 * @wdev: Pointer to wireless device
4272 * @data: Pointer to data
4273 * @data_len: Data length
4274 *
4275 * Return: 0 on success, negative errno on failure
4276 */
4277static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4278 struct wireless_dev *wdev,
4279 const void *data,
4280 int data_len)
4281{
4282 int ret = 0;
4283
4284 cds_ssr_protect(__func__);
4285 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
4286 data, data_len);
4287 cds_ssr_unprotect(__func__);
4288
4289 return ret;
4290}
4291
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304292static const struct
4293nla_policy
4294qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
4295 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
4296};
4297
4298/**
4299 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
4300 * @wiphy: WIPHY structure pointer
4301 * @wdev: Wireless device structure pointer
4302 * @data: Pointer to the data received
4303 * @data_len: Length of the data received
4304 *
4305 * This function is used to get link properties like nss, rate flags and
4306 * operating frequency for the active connection with the given peer.
4307 *
4308 * Return: 0 on success and errno on failure
4309 */
4310static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4311 struct wireless_dev *wdev,
4312 const void *data,
4313 int data_len)
4314{
4315 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4316 struct net_device *dev = wdev->netdev;
4317 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4318 hdd_station_ctx_t *hdd_sta_ctx;
4319 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05304320 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304321 uint32_t sta_id;
4322 struct sk_buff *reply_skb;
4323 uint32_t rate_flags = 0;
4324 uint8_t nss;
4325 uint8_t final_rate_flags = 0;
4326 uint32_t freq;
4327
4328 ENTER();
4329
Anurag Chouhan6d760662016-02-20 16:05:43 +05304330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304331 hdd_err("Command not allowed in FTM mode");
4332 return -EPERM;
4333 }
4334
4335 if (0 != wlan_hdd_validate_context(hdd_ctx))
4336 return -EINVAL;
4337
4338 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
4339 qca_wlan_vendor_attr_policy)) {
4340 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid attribute"));
4341 return -EINVAL;
4342 }
4343
4344 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
4345 hddLog(CDF_TRACE_LEVEL_ERROR,
4346 FL("Attribute peerMac not provided for mode=%d"),
4347 adapter->device_mode);
4348 return -EINVAL;
4349 }
4350
4351 cdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05304352 QDF_MAC_ADDR_SIZE);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304353 hddLog(CDF_TRACE_LEVEL_INFO,
4354 FL("peerMac="MAC_ADDRESS_STR" for device_mode:%d"),
4355 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
4356
4357 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4358 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
4359 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4360 if ((hdd_sta_ctx->conn_info.connState !=
4361 eConnectionState_Associated) ||
4362 !cdf_mem_compare(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304363 peer_mac, QDF_MAC_ADDR_SIZE)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304364 hddLog(CDF_TRACE_LEVEL_ERROR,
4365 FL("Not Associated to mac "MAC_ADDRESS_STR),
4366 MAC_ADDR_ARRAY(peer_mac));
4367 return -EINVAL;
4368 }
4369
4370 nss = hdd_sta_ctx->conn_info.nss;
4371 freq = cds_chan_to_freq(
4372 hdd_sta_ctx->conn_info.operationChannel);
4373 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
4374 } else if (adapter->device_mode == WLAN_HDD_P2P_GO ||
4375 adapter->device_mode == WLAN_HDD_SOFTAP) {
4376
4377 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
4378 if (adapter->aStaInfo[sta_id].isUsed &&
4379 !cdf_is_macaddr_broadcast(
4380 &adapter->aStaInfo[sta_id].macAddrSTA) &&
4381 cdf_mem_compare(
4382 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304383 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304384 break;
4385 }
4386
4387 if (WLAN_MAX_STA_COUNT == sta_id) {
4388 hddLog(CDF_TRACE_LEVEL_ERROR,
4389 FL("No active peer with mac="MAC_ADDRESS_STR),
4390 MAC_ADDR_ARRAY(peer_mac));
4391 return -EINVAL;
4392 }
4393
4394 nss = adapter->aStaInfo[sta_id].nss;
4395 freq = cds_chan_to_freq(
4396 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
4397 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
4398 } else {
4399 hddLog(CDF_TRACE_LEVEL_ERROR,
4400 FL("Not Associated! with mac "MAC_ADDRESS_STR),
4401 MAC_ADDR_ARRAY(peer_mac));
4402 return -EINVAL;
4403 }
4404
4405 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
4406 if (rate_flags & eHAL_TX_RATE_VHT80) {
4407 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4408 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
4409 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
4410 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4411 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
4412 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
4413 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4414 } else if (rate_flags &
4415 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
4416 final_rate_flags |= RATE_INFO_FLAGS_MCS;
4417 if (rate_flags & eHAL_TX_RATE_HT40)
4418 final_rate_flags |=
4419 RATE_INFO_FLAGS_40_MHZ_WIDTH;
4420 }
4421
4422 if (rate_flags & eHAL_TX_RATE_SGI) {
4423 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
4424 final_rate_flags |= RATE_INFO_FLAGS_MCS;
4425 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
4426 }
4427 }
4428
4429 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4430 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
4431
4432 if (NULL == reply_skb) {
4433 hddLog(CDF_TRACE_LEVEL_ERROR,
4434 FL("getLinkProperties: skb alloc failed"));
4435 return -EINVAL;
4436 }
4437
4438 if (nla_put_u8(reply_skb,
4439 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
4440 nss) ||
4441 nla_put_u8(reply_skb,
4442 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
4443 final_rate_flags) ||
4444 nla_put_u32(reply_skb,
4445 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
4446 freq)) {
4447 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla_put failed"));
4448 kfree_skb(reply_skb);
4449 return -EINVAL;
4450 }
4451
4452 return cfg80211_vendor_cmd_reply(reply_skb);
4453}
4454
4455/**
4456 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
4457 * properties.
4458 * @wiphy: WIPHY structure pointer
4459 * @wdev: Wireless device structure pointer
4460 * @data: Pointer to the data received
4461 * @data_len: Length of the data received
4462 *
4463 * This function is used to get link properties like nss, rate flags and
4464 * operating frequency for the active connection with the given peer.
4465 *
4466 * Return: 0 on success and errno on failure
4467 */
4468static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4469 struct wireless_dev *wdev,
4470 const void *data,
4471 int data_len)
4472{
4473 int ret = 0;
4474
4475 cds_ssr_protect(__func__);
4476 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
4477 wdev, data, data_len);
4478 cds_ssr_unprotect(__func__);
4479
4480 return ret;
4481}
4482
Peng Xu278d0122015-09-24 16:34:17 -07004483static const struct
4484nla_policy
4485qca_wlan_vendor_ota_test_policy
4486[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
4487 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
4488};
4489
4490/**
4491 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
4492 * @wiphy: Pointer to wireless phy
4493 * @wdev: Pointer to wireless device
4494 * @data: Pointer to data
4495 * @data_len: Data length
4496 *
4497 * Return: 0 on success, negative errno on failure
4498 */
4499static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4500 struct wireless_dev *wdev,
4501 const void *data,
4502 int data_len)
4503{
4504 struct net_device *dev = wdev->netdev;
4505 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4506 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
4507 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4508 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
4509 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304510 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07004511 uint32_t current_roam_state;
4512
Anurag Chouhan6d760662016-02-20 16:05:43 +05304513 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07004514 hdd_err("Command not allowed in FTM mode");
4515 return -EPERM;
4516 }
4517
4518 if (0 != wlan_hdd_validate_context(hdd_ctx))
4519 return -EINVAL;
4520
4521 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
4522 data, data_len,
4523 qca_wlan_vendor_ota_test_policy)) {
4524 hdd_err("invalid attr");
4525 return -EINVAL;
4526 }
4527
4528 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
4529 hdd_err("attr ota test failed");
4530 return -EINVAL;
4531 }
4532
4533 ota_enable = nla_get_u8(
4534 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
4535
4536 hdd_info(" OTA test enable = %d", ota_enable);
4537 if (ota_enable != 1) {
4538 hdd_err("Invalid value, only enable test mode is supported!");
4539 return -EINVAL;
4540 }
4541
4542 current_roam_state =
4543 sme_get_current_roam_state(hal, adapter->sessionId);
4544 status = sme_stop_roaming(hal, adapter->sessionId,
4545 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304546 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004547 hdd_err("Enable/Disable roaming failed");
4548 return -EINVAL;
4549 }
4550
4551 status = sme_ps_enable_disable(hal, adapter->sessionId,
4552 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304553 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004554 hdd_err("Enable/Disable power save failed");
4555 /* restore previous roaming setting */
4556 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
4557 current_roam_state == eCSR_ROAMING_STATE_JOINED)
4558 status = sme_start_roaming(hal, adapter->sessionId,
4559 eCsrHddIssued);
4560 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
4561 current_roam_state == eCSR_ROAMING_STATE_IDLE)
4562 status = sme_stop_roaming(hal, adapter->sessionId,
4563 eCsrHddIssued);
4564
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304565 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07004566 hdd_err("Restoring roaming state failed");
4567
4568 return -EINVAL;
4569 }
4570
4571
4572 return 0;
4573}
4574
4575/**
4576 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
4577 * @wiphy: Pointer to wireless phy
4578 * @wdev: Pointer to wireless device
4579 * @data: Pointer to data
4580 * @data_len: Data length
4581 *
4582 * Return: 0 on success, negative errno on failure
4583 */
4584static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4585 struct wireless_dev *wdev,
4586 const void *data,
4587 int data_len)
4588{
4589 int ret = 0;
4590
4591 cds_ssr_protect(__func__);
4592 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
4593 cds_ssr_unprotect(__func__);
4594
4595 return ret;
4596}
4597
Peng Xu4d67c8f2015-10-16 16:02:26 -07004598/**
4599 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4600 * @wiphy: Pointer to wireless phy
4601 * @wdev: Pointer to wireless device
4602 * @data: Pointer to data
4603 * @data_len: Data length
4604 *
4605 * Return: 0 on success, negative errno on failure
4606 */
4607static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4608 struct wireless_dev *wdev,
4609 const void *data,
4610 int data_len)
4611{
4612 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4613 struct net_device *dev = wdev->netdev;
4614 hdd_adapter_t *adapter = NULL;
4615 int ret = 0;
4616 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
4617 uint8_t scale_value;
4618
4619 ret = wlan_hdd_validate_context(hdd_ctx);
4620 if (ret)
4621 return ret;
4622
4623 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4624
4625 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
4626 data, data_len, NULL)) {
4627 hdd_err("Invalid ATTR");
4628 return -EINVAL;
4629 }
4630
4631 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
4632 hdd_err("attr tx power scale failed");
4633 return -EINVAL;
4634 }
4635
4636 scale_value = nla_get_u8(tb
4637 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
4638
4639 if (scale_value > MAX_TXPOWER_SCALE) {
4640 hdd_err("Invalid tx power scale level");
4641 return -EINVAL;
4642 }
4643
4644 ret = wma_set_tx_power_scale(adapter->sessionId, scale_value);
4645
4646 if (ret != 0) {
4647 hdd_err("Set tx power scale failed");
4648 return -EINVAL;
4649 }
4650
4651 return 0;
4652}
4653
4654/**
4655 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4656 * @wiphy: Pointer to wireless phy
4657 * @wdev: Pointer to wireless device
4658 * @data: Pointer to data
4659 * @data_len: Data length
4660 *
4661 * Return: 0 on success, negative errno on failure
4662 */
4663static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4664 struct wireless_dev *wdev,
4665 const void *data,
4666 int data_len)
4667{
4668 int ret = 0;
4669
4670 cds_ssr_protect(__func__);
4671 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
4672 data, data_len);
4673 cds_ssr_unprotect(__func__);
4674
4675 return ret;
4676}
4677
4678/**
4679 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4680 * @wiphy: Pointer to wireless phy
4681 * @wdev: Pointer to wireless device
4682 * @data: Pointer to data
4683 * @data_len: Data length
4684 *
4685 * Return: 0 on success, negative errno on failure
4686 */
4687static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4688 struct wireless_dev *wdev,
4689 const void *data,
4690 int data_len)
4691{
4692 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4693 struct net_device *dev = wdev->netdev;
4694 hdd_adapter_t *adapter = NULL;
4695 int ret = 0;
4696 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
4697 uint8_t scale_value;
4698
4699 ret = wlan_hdd_validate_context(hdd_ctx);
4700 if (ret)
4701 return ret;
4702
4703 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4704
4705 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
4706 data, data_len, NULL)) {
4707 hdd_err("Invalid ATTR");
4708 return -EINVAL;
4709 }
4710
4711 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
4712 hdd_err("attr tx power decrease db value failed");
4713 return -EINVAL;
4714 }
4715
4716 scale_value = nla_get_u8(tb
4717 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
4718
4719 ret = wma_set_tx_power_scale_decr_db(adapter->sessionId, scale_value);
4720
4721 if (ret != 0) {
4722 hdd_err("Set tx power decrease db failed");
4723 return -EINVAL;
4724 }
4725
4726 return 0;
4727}
4728
4729/**
4730 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4731 * @wiphy: Pointer to wireless phy
4732 * @wdev: Pointer to wireless device
4733 * @data: Pointer to data
4734 * @data_len: Data length
4735 *
4736 * Return: 0 on success, negative errno on failure
4737 */
4738static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4739 struct wireless_dev *wdev,
4740 const void *data,
4741 int data_len)
4742{
4743 int ret = 0;
4744
4745 cds_ssr_protect(__func__);
4746 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
4747 data, data_len);
4748 cds_ssr_unprotect(__func__);
4749
4750 return ret;
4751}
4752
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
4754 {
4755 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4756 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
4757 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4758 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4759 .doit = is_driver_dfs_capable
4760 },
4761
4762#ifdef WLAN_FEATURE_NAN
4763 {
4764 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4765 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
4766 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4767 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4768 .doit = wlan_hdd_cfg80211_nan_request
4769 },
4770#endif
4771
4772#ifdef WLAN_FEATURE_STATS_EXT
4773 {
4774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4775 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
4776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4777 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4778 .doit = wlan_hdd_cfg80211_stats_ext_request
4779 },
4780#endif
4781#ifdef FEATURE_WLAN_EXTSCAN
4782 {
4783 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4784 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
4785 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4786 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4787 .doit = wlan_hdd_cfg80211_extscan_start
4788 },
4789 {
4790 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4791 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
4792 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4793 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4794 .doit = wlan_hdd_cfg80211_extscan_stop
4795 },
4796 {
4797 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4798 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
4799 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4800 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
4801 },
4802 {
4803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4804 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
4805 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4806 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4807 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
4808 },
4809 {
4810 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4811 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
4812 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4813 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4814 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
4815 },
4816 {
4817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4818 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
4819 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4820 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4821 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
4822 },
4823 {
4824 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4825 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
4826 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4827 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4828 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
4829 },
4830 {
4831 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4832 .info.subcmd =
4833 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
4834 .flags =
4835 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4836 WIPHY_VENDOR_CMD_NEED_RUNNING,
4837 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
4838 },
4839 {
4840 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4841 .info.subcmd =
4842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
4843 .flags =
4844 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4845 WIPHY_VENDOR_CMD_NEED_RUNNING,
4846 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
4847 },
4848 {
4849 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4850 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
4851 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4852 WIPHY_VENDOR_CMD_NEED_NETDEV |
4853 WIPHY_VENDOR_CMD_NEED_RUNNING,
4854 .doit = wlan_hdd_cfg80211_set_epno_list
4855 },
4856#endif /* FEATURE_WLAN_EXTSCAN */
4857
4858#ifdef WLAN_FEATURE_LINK_LAYER_STATS
4859 {
4860 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4861 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
4862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4863 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4864 .doit = wlan_hdd_cfg80211_ll_stats_clear
4865 },
4866
4867 {
4868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
4870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4871 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4872 .doit = wlan_hdd_cfg80211_ll_stats_set
4873 },
4874
4875 {
4876 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4877 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
4878 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4879 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4880 .doit = wlan_hdd_cfg80211_ll_stats_get
4881 },
4882#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
4883#ifdef FEATURE_WLAN_TDLS
4884 {
4885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4886 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
4887 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4888 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4889 .doit = wlan_hdd_cfg80211_exttdls_enable
4890 },
4891 {
4892 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4893 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
4894 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4895 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4896 .doit = wlan_hdd_cfg80211_exttdls_disable
4897 },
4898 {
4899 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4900 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
4901 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4902 .doit = wlan_hdd_cfg80211_exttdls_get_status
4903 },
4904#endif
4905 {
4906 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4907 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
4908 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4909 .doit = wlan_hdd_cfg80211_get_supported_features
4910 },
4911 {
4912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
4914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4915 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
4916 },
4917 {
4918 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4919 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
4920 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4921 .doit = cds_cfg80211_get_concurrency_matrix
4922 },
4923 {
4924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
4926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4927 WIPHY_VENDOR_CMD_NEED_NETDEV,
4928 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
4929 },
4930
4931 {
4932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
4934 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4935 WIPHY_VENDOR_CMD_NEED_NETDEV |
4936 WIPHY_VENDOR_CMD_NEED_RUNNING,
4937 .doit = wlan_hdd_cfg80211_do_acs
4938 },
4939
4940 {
4941 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4942 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
4943 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4944 WIPHY_VENDOR_CMD_NEED_NETDEV,
4945 .doit = wlan_hdd_cfg80211_get_features
4946 },
4947#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4948 {
4949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
4951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4952 WIPHY_VENDOR_CMD_NEED_NETDEV |
4953 WIPHY_VENDOR_CMD_NEED_RUNNING,
4954 .doit = wlan_hdd_cfg80211_keymgmt_set_key
4955 },
4956#endif
4957#ifdef FEATURE_WLAN_EXTSCAN
4958 {
4959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
4961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4962 WIPHY_VENDOR_CMD_NEED_NETDEV |
4963 WIPHY_VENDOR_CMD_NEED_RUNNING,
4964 .doit = wlan_hdd_cfg80211_set_passpoint_list
4965 },
4966 {
4967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4968 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
4969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4970 WIPHY_VENDOR_CMD_NEED_NETDEV |
4971 WIPHY_VENDOR_CMD_NEED_RUNNING,
4972 .doit = wlan_hdd_cfg80211_reset_passpoint_list
4973 },
4974 {
4975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
4977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4978 WIPHY_VENDOR_CMD_NEED_NETDEV |
4979 WIPHY_VENDOR_CMD_NEED_RUNNING,
4980 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
4981 },
4982 {
4983 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4984 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
4985 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4986 WIPHY_VENDOR_CMD_NEED_NETDEV |
4987 WIPHY_VENDOR_CMD_NEED_RUNNING,
4988 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
4989 },
4990#endif /* FEATURE_WLAN_EXTSCAN */
4991 {
4992 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4993 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
4994 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4995 WIPHY_VENDOR_CMD_NEED_NETDEV,
4996 .doit = wlan_hdd_cfg80211_get_wifi_info
4997 },
4998 {
4999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
5001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5002 WIPHY_VENDOR_CMD_NEED_NETDEV |
5003 WIPHY_VENDOR_CMD_NEED_RUNNING,
5004 .doit = wlan_hdd_cfg80211_wifi_configuration_set
5005 },
5006 {
5007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
5009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5010 WIPHY_VENDOR_CMD_NEED_NETDEV,
5011 .doit = wlan_hdd_cfg80211_set_ext_roam_params
5012 },
5013 {
5014 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5015 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
5016 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5017 WIPHY_VENDOR_CMD_NEED_NETDEV,
5018 .doit = wlan_hdd_cfg80211_wifi_logger_start
5019 },
5020 {
5021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5022 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
5023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5024 WIPHY_VENDOR_CMD_NEED_NETDEV,
5025 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
5026 },
5027 {
5028 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5029 .info.subcmd =
5030 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
5031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5032 WIPHY_VENDOR_CMD_NEED_NETDEV |
5033 WIPHY_VENDOR_CMD_NEED_RUNNING,
5034 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
5035 },
5036 {
5037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5038 .info.subcmd =
5039 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
5040 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5041 WIPHY_VENDOR_CMD_NEED_NETDEV |
5042 WIPHY_VENDOR_CMD_NEED_RUNNING,
5043 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
5044 },
5045#ifdef FEATURE_WLAN_TDLS
5046 {
5047 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5048 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
5049 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5050 WIPHY_VENDOR_CMD_NEED_NETDEV |
5051 WIPHY_VENDOR_CMD_NEED_RUNNING,
5052 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
5053 },
5054#endif
5055#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5056 {
5057 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5058 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
5059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5060 WIPHY_VENDOR_CMD_NEED_NETDEV |
5061 WIPHY_VENDOR_CMD_NEED_RUNNING,
5062 .doit = wlan_hdd_cfg80211_offloaded_packets
5063 },
5064#endif
5065 {
5066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
5068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5069 WIPHY_VENDOR_CMD_NEED_NETDEV |
5070 WIPHY_VENDOR_CMD_NEED_RUNNING,
5071 .doit = wlan_hdd_cfg80211_monitor_rssi
5072 },
5073 {
5074 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5075 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
5076 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5077 WIPHY_VENDOR_CMD_NEED_NETDEV |
5078 WIPHY_VENDOR_CMD_NEED_RUNNING,
5079 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
5080 },
5081#ifdef WLAN_FEATURE_MEMDUMP
5082 {
5083 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5084 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
5085 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5086 WIPHY_VENDOR_CMD_NEED_NETDEV |
5087 WIPHY_VENDOR_CMD_NEED_RUNNING,
5088 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
5089 },
5090#endif /* WLAN_FEATURE_MEMDUMP */
5091 {
5092 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5093 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
5094 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5095 WIPHY_VENDOR_CMD_NEED_NETDEV |
5096 WIPHY_VENDOR_CMD_NEED_RUNNING,
5097 .doit = wlan_hdd_cfg80211_vendor_scan
5098 },
5099
5100 /* OCB commands */
5101 {
5102 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5103 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
5104 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5105 WIPHY_VENDOR_CMD_NEED_NETDEV |
5106 WIPHY_VENDOR_CMD_NEED_RUNNING,
5107 .doit = wlan_hdd_cfg80211_ocb_set_config
5108 },
5109 {
5110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5111 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
5112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5113 WIPHY_VENDOR_CMD_NEED_NETDEV |
5114 WIPHY_VENDOR_CMD_NEED_RUNNING,
5115 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
5116 },
5117 {
5118 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5119 .info.subcmd =
5120 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
5121 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5122 WIPHY_VENDOR_CMD_NEED_NETDEV |
5123 WIPHY_VENDOR_CMD_NEED_RUNNING,
5124 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
5125 },
5126 {
5127 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5128 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
5129 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5130 WIPHY_VENDOR_CMD_NEED_NETDEV |
5131 WIPHY_VENDOR_CMD_NEED_RUNNING,
5132 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
5133 },
5134 {
5135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
5137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5138 WIPHY_VENDOR_CMD_NEED_NETDEV |
5139 WIPHY_VENDOR_CMD_NEED_RUNNING,
5140 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
5141 },
5142 {
5143 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5144 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
5145 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5146 WIPHY_VENDOR_CMD_NEED_NETDEV |
5147 WIPHY_VENDOR_CMD_NEED_RUNNING,
5148 .doit = wlan_hdd_cfg80211_dcc_get_stats
5149 },
5150 {
5151 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5152 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
5153 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5154 WIPHY_VENDOR_CMD_NEED_NETDEV |
5155 WIPHY_VENDOR_CMD_NEED_RUNNING,
5156 .doit = wlan_hdd_cfg80211_dcc_clear_stats
5157 },
5158 {
5159 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5160 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
5161 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5162 WIPHY_VENDOR_CMD_NEED_NETDEV |
5163 WIPHY_VENDOR_CMD_NEED_RUNNING,
5164 .doit = wlan_hdd_cfg80211_dcc_update_ndl
5165 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305166 {
5167 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5168 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
5169 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5170 WIPHY_VENDOR_CMD_NEED_NETDEV |
5171 WIPHY_VENDOR_CMD_NEED_RUNNING,
5172 .doit = wlan_hdd_cfg80211_get_link_properties
5173 },
Peng Xu278d0122015-09-24 16:34:17 -07005174 {
5175 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
5176 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5177 WIPHY_VENDOR_CMD_NEED_NETDEV |
5178 WIPHY_VENDOR_CMD_NEED_RUNNING,
5179 .doit = wlan_hdd_cfg80211_set_ota_test
5180 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08005181#ifdef FEATURE_LFR_SUBNET_DETECTION
5182 {
5183 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5184 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
5185 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5186 WIPHY_VENDOR_CMD_NEED_NETDEV |
5187 WIPHY_VENDOR_CMD_NEED_RUNNING,
5188 .doit = wlan_hdd_cfg80211_set_gateway_params
5189 },
5190#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07005191 {
5192 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
5193 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5194 WIPHY_VENDOR_CMD_NEED_NETDEV |
5195 WIPHY_VENDOR_CMD_NEED_RUNNING,
5196 .doit = wlan_hdd_cfg80211_txpower_scale
5197 },
5198 {
5199 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5200 .info.subcmd =
5201 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
5202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5203 WIPHY_VENDOR_CMD_NEED_NETDEV |
5204 WIPHY_VENDOR_CMD_NEED_RUNNING,
5205 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
5206 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207};
5208
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005209/**
5210 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
5211 * @priv_size: Size of the hdd context.
5212 *
5213 * Allocate wiphy context and hdd context.
5214 *
5215 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005216 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005217hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218{
5219 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005220 hdd_context_t *hdd_ctx;
5221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 ENTER();
5223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
5225
5226 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005227 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005228 return NULL;
5229 }
5230
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005231 hdd_ctx = wiphy_priv(wiphy);
5232
5233 hdd_ctx->wiphy = wiphy;
5234
5235 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236}
5237
5238/*
5239 * FUNCTION: wlan_hdd_cfg80211_update_band
5240 * This function is called from the supplicant through a
5241 * private ioctl to change the band value
5242 */
5243int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
5244{
5245 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07005246 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247
5248 ENTER();
5249
5250 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5251
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005252 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005254
5255 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5256 struct ieee80211_supported_band *band = wiphy->bands[i];
5257
5258 channelEnabledState =
5259 cds_get_channel_state(band->channels[j].
5260 hw_value);
5261
5262 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
5263 /* 5G only */
5264#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5265 /* Enable Social channels for P2P */
5266 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5267 (band->channels[j].center_freq)
5268 && CHANNEL_STATE_ENABLE ==
5269 channelEnabledState)
5270 band->channels[j].flags &=
5271 ~IEEE80211_CHAN_DISABLED;
5272 else
5273#endif
5274 band->channels[j].flags |=
5275 IEEE80211_CHAN_DISABLED;
5276 continue;
5277 } else if (IEEE80211_BAND_5GHZ == i &&
5278 eCSR_BAND_24 == eBand) {
5279 /* 2G only */
5280 band->channels[j].flags |=
5281 IEEE80211_CHAN_DISABLED;
5282 continue;
5283 }
5284
5285 if (CHANNEL_STATE_DISABLE == channelEnabledState ||
5286 CHANNEL_STATE_INVALID == channelEnabledState) {
5287 band->channels[j].flags |=
5288 IEEE80211_CHAN_DISABLED;
5289 } else if (CHANNEL_STATE_DFS == channelEnabledState) {
5290 band->channels[j].flags &=
5291 ~IEEE80211_CHAN_DISABLED;
5292 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
5293 } else {
5294 band->channels[j].flags &=
5295 ~(IEEE80211_CHAN_DISABLED |
5296 IEEE80211_CHAN_RADAR);
5297 }
5298 }
5299 }
5300 return 0;
5301}
5302
5303/*
5304 * FUNCTION: wlan_hdd_cfg80211_init
5305 * This function is called by hdd_wlan_startup()
5306 * during initialization.
5307 * This function is used to initialize and register wiphy structure.
5308 */
5309int wlan_hdd_cfg80211_init(struct device *dev,
5310 struct wiphy *wiphy, struct hdd_config *pCfg)
5311{
5312 int i, j;
5313 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5314
5315 ENTER();
5316
5317 /* Now bind the underlying wlan device with wiphy */
5318 set_wiphy_dev(wiphy, dev);
5319
5320 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
5321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
5323 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005324 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325#else
5326 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005327 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328#endif
5329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
5331 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
5332 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
5333#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
5334 | WIPHY_FLAG_4ADDR_STATION
5335#endif
5336 | WIPHY_FLAG_OFFCHAN_TX;
5337
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5339 wiphy->wowlan = &wowlan_support_cfg80211_init;
5340#else
5341 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
5342 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
5343 wiphy->wowlan.pattern_min_len = 1;
5344 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
5345#endif
5346
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07005347 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348#ifdef FEATURE_WLAN_ESE
5349 || pCfg->isEseIniFeatureEnabled
5350#endif
5351 ) {
5352 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
5353 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354#ifdef FEATURE_WLAN_TDLS
5355 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
5356 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
5357#endif
5358
5359 wiphy->features |= NL80211_FEATURE_HT_IBSS;
5360
5361#ifdef FEATURE_WLAN_SCAN_PNO
5362 if (pCfg->configPNOScanSupport) {
5363 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5364 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
5365 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
5366 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
5367 }
5368#endif /*FEATURE_WLAN_SCAN_PNO */
5369
5370#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05305371 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372#endif
5373
5374 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
5375 driver can still register regulatory callback and
5376 it will get regulatory settings in wiphy->band[], but
5377 driver need to determine what to do with both
5378 regulatory settings */
5379
5380 wiphy->reg_notifier = hdd_reg_notifier;
5381
5382#if defined QCA_WIFI_FTM
5383}
5384#endif
5385
5386 wiphy->max_scan_ssids = MAX_SCAN_SSID;
5387
5388 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
5389
5390 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
5391
5392 /* Supports STATION & AD-HOC modes right now */
5393 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
5394 | BIT(NL80211_IFTYPE_ADHOC)
5395 | BIT(NL80211_IFTYPE_P2P_CLIENT)
5396 | BIT(NL80211_IFTYPE_P2P_GO)
5397 | BIT(NL80211_IFTYPE_AP);
5398
5399 if (pCfg->advertiseConcurrentOperation) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400 if (pCfg->enableMCC) {
5401 int i;
5402 for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination);
5403 i++) {
5404 if (!pCfg->allowMCCGODiffBI)
5405 wlan_hdd_iface_combination[i].
5406 beacon_int_infra_match = true;
5407 }
5408 }
5409 wiphy->n_iface_combinations =
5410 ARRAY_SIZE(wlan_hdd_iface_combination);
5411 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 }
5413
5414 /* Before registering we need to update the ht capabilitied based
5415 * on ini values*/
5416 if (!pCfg->ShortGI20MhzEnable) {
5417 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5418 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5419 wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &=
5420 ~IEEE80211_HT_CAP_SGI_20;
5421 }
5422
5423 if (!pCfg->ShortGI40MhzEnable) {
5424 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
5425 }
5426
5427 if (!pCfg->nChannelBondingMode5GHz) {
5428 wlan_hdd_band_5_ghz.ht_cap.cap &=
5429 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5430 }
5431
5432 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
5433 if (true == hdd_is_5g_supported(pHddCtx)) {
5434 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
5435 }
5436
5437 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5438
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005439 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441
5442 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5443 struct ieee80211_supported_band *band = wiphy->bands[i];
5444
5445 if (IEEE80211_BAND_2GHZ == i &&
5446 eCSR_BAND_5G == pCfg->nBandCapability) {
5447 /* 5G only */
5448#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5449 /* Enable social channels for P2P */
5450 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5451 (band->channels[j].center_freq))
5452 band->channels[j].flags &=
5453 ~IEEE80211_CHAN_DISABLED;
5454 else
5455#endif
5456 band->channels[j].flags |=
5457 IEEE80211_CHAN_DISABLED;
5458 continue;
5459 } else if (IEEE80211_BAND_5GHZ == i &&
5460 eCSR_BAND_24 == pCfg->nBandCapability) {
5461 /* 2G only */
5462 band->channels[j].flags |=
5463 IEEE80211_CHAN_DISABLED;
5464 continue;
5465 }
5466 }
5467 }
5468 /*Initialise the supported cipher suite details */
5469 wiphy->cipher_suites = hdd_cipher_suites;
5470 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
5471
5472 /*signal strength in mBm (100*dBm) */
5473 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
5474 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
5475
Anurag Chouhan6d760662016-02-20 16:05:43 +05305476 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 wiphy->n_vendor_commands =
5478 ARRAY_SIZE(hdd_wiphy_vendor_commands);
5479 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
5480
5481 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
5482 wiphy->n_vendor_events =
5483 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
5484 }
5485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 if (pCfg->enableDFSMasterCap) {
5487 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
5488 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489
5490 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
5491
5492#ifdef QCA_HT_2040_COEX
5493 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
5494#endif
5495
Abhishek Singh1bdb1572015-10-16 16:24:19 +05305496 hdd_add_channel_switch_support(&wiphy->flags);
5497
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005498 EXIT();
5499 return 0;
5500}
5501
5502/*
5503 * In this function, wiphy structure is updated after CDF
5504 * initialization. In wlan_hdd_cfg80211_init, only the
5505 * default values will be initialized. The final initialization
5506 * of all required members can be done here.
5507 */
5508void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
5509{
5510 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
5511}
5512
5513/* In this function we are registering wiphy. */
5514int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
5515{
5516 ENTER();
5517 /* Register our wiphy dev with cfg80211 */
5518 if (0 > wiphy_register(wiphy)) {
5519 /* print error */
5520 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: wiphy register failed",
5521 __func__);
5522 return -EIO;
5523 }
5524
5525 EXIT();
5526 return 0;
5527}
5528
5529/*
5530 HDD function to update wiphy capability based on target offload status.
5531
5532 wlan_hdd_cfg80211_init() does initialization of all wiphy related
5533 capability even before downloading firmware to the target. In discrete
5534 case, host will get know certain offload capability (say sched_scan
5535 caps) only after downloading firmware to the target and target boots up.
5536 This function is used to override setting done in wlan_hdd_cfg80211_init()
5537 based on target capability.
5538 */
5539void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
5540{
5541#ifdef FEATURE_WLAN_SCAN_PNO
5542 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5543 struct hdd_config *pCfg = pHddCtx->config;
5544
5545 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
5546 * control comes here. Here just we need to clear it if firmware doesn't
5547 * have PNO support. */
5548 if (!pCfg->PnoOffload) {
5549 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5550 wiphy->max_sched_scan_ssids = 0;
5551 wiphy->max_match_sets = 0;
5552 wiphy->max_sched_scan_ie_len = 0;
5553 }
5554#endif
5555}
5556
5557/* This function registers for all frame which supplicant is interested in */
5558void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
5559{
5560 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5561 /* Register for all P2P action, public action etc frames */
5562 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5563
5564 ENTER();
5565
Abhishek Singh7996eb72015-12-30 17:24:02 +05305566 /* Register frame indication call back */
5567 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
5568
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 /* Right now we are registering these frame when driver is getting
5570 initialized. Once we will move to 2.6.37 kernel, in which we have
5571 frame register ops, we will move this code as a part of that */
5572 /* GAS Initial Request */
5573 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5574 (uint8_t *) GAS_INITIAL_REQ,
5575 GAS_INITIAL_REQ_SIZE);
5576
5577 /* GAS Initial Response */
5578 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5579 (uint8_t *) GAS_INITIAL_RSP,
5580 GAS_INITIAL_RSP_SIZE);
5581
5582 /* GAS Comeback Request */
5583 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5584 (uint8_t *) GAS_COMEBACK_REQ,
5585 GAS_COMEBACK_REQ_SIZE);
5586
5587 /* GAS Comeback Response */
5588 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5589 (uint8_t *) GAS_COMEBACK_RSP,
5590 GAS_COMEBACK_RSP_SIZE);
5591
5592 /* P2P Public Action */
5593 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5594 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5595 P2P_PUBLIC_ACTION_FRAME_SIZE);
5596
5597 /* P2P Action */
5598 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5599 (uint8_t *) P2P_ACTION_FRAME,
5600 P2P_ACTION_FRAME_SIZE);
5601
5602 /* WNM BSS Transition Request frame */
5603 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5604 (uint8_t *) WNM_BSS_ACTION_FRAME,
5605 WNM_BSS_ACTION_FRAME_SIZE);
5606
5607 /* WNM-Notification */
5608 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
5609 (uint8_t *) WNM_NOTIFICATION_FRAME,
5610 WNM_NOTIFICATION_FRAME_SIZE);
5611}
5612
5613void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
5614{
5615 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5616 /* Register for all P2P action, public action etc frames */
5617 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5618
5619 ENTER();
5620
5621 /* Right now we are registering these frame when driver is getting
5622 initialized. Once we will move to 2.6.37 kernel, in which we have
5623 frame register ops, we will move this code as a part of that */
5624 /* GAS Initial Request */
5625
5626 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5627 (uint8_t *) GAS_INITIAL_REQ,
5628 GAS_INITIAL_REQ_SIZE);
5629
5630 /* GAS Initial Response */
5631 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5632 (uint8_t *) GAS_INITIAL_RSP,
5633 GAS_INITIAL_RSP_SIZE);
5634
5635 /* GAS Comeback Request */
5636 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5637 (uint8_t *) GAS_COMEBACK_REQ,
5638 GAS_COMEBACK_REQ_SIZE);
5639
5640 /* GAS Comeback Response */
5641 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5642 (uint8_t *) GAS_COMEBACK_RSP,
5643 GAS_COMEBACK_RSP_SIZE);
5644
5645 /* P2P Public Action */
5646 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5647 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5648 P2P_PUBLIC_ACTION_FRAME_SIZE);
5649
5650 /* P2P Action */
5651 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5652 (uint8_t *) P2P_ACTION_FRAME,
5653 P2P_ACTION_FRAME_SIZE);
5654
5655 /* WNM-Notification */
5656 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
5657 (uint8_t *) WNM_NOTIFICATION_FRAME,
5658 WNM_NOTIFICATION_FRAME_SIZE);
5659}
5660
5661#ifdef FEATURE_WLAN_WAPI
5662void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
5663 const uint8_t *mac_addr, const uint8_t *key,
5664 int key_Len)
5665{
5666 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5667 tCsrRoamSetKey setKey;
5668 bool isConnected = true;
5669 int status = 0;
5670 uint32_t roamId = 0xFF;
5671 uint8_t *pKeyPtr = NULL;
5672 int n = 0;
5673
5674 hddLog(LOG1, "Device_mode %s(%d)",
5675 hdd_device_mode_to_string(pAdapter->device_mode),
5676 pAdapter->device_mode);
5677
5678 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
5679 setKey.keyId = key_index; /* Store Key ID */
5680 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
5681 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
5682 setKey.paeRole = 0; /* the PAE role */
5683 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
5684 cdf_set_macaddr_broadcast(&setKey.peerMac);
5685 } else {
Anurag Chouhan6d760662016-02-20 16:05:43 +05305686 cdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005687 }
5688 setKey.keyLength = key_Len;
5689 pKeyPtr = setKey.Key;
5690 memcpy(pKeyPtr, key, key_Len);
5691
5692 hddLog(CDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x",
5693 __func__, key_Len);
5694 for (n = 0; n < key_Len; n++)
5695 hddLog(CDF_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
5696 __func__, n, setKey.Key[n]);
5697
5698 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
5699 if (isConnected) {
5700 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
5701 pAdapter->sessionId, &setKey, &roamId);
5702 }
5703 if (status != 0) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05305704 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005705 "[%4d] sme_roam_set_key returned ERROR status= %d",
5706 __LINE__, status);
5707 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
5708 }
5709}
5710#endif /* FEATURE_WLAN_WAPI */
5711
5712uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
5713 uint8_t eid)
5714{
5715 int left = length;
5716 uint8_t *ptr = (uint8_t *)ies_ptr;
5717 uint8_t elem_id, elem_len;
5718
5719 while (left >= 2) {
5720 elem_id = ptr[0];
5721 elem_len = ptr[1];
5722 left -= 2;
5723 if (elem_len > left) {
5724 hddLog(CDF_TRACE_LEVEL_FATAL,
5725 FL("Invalid IEs eid = %d elem_len=%d left=%d"),
5726 eid, elem_len, left);
5727 return NULL;
5728 }
5729 if (elem_id == eid) {
5730 return ptr;
5731 }
5732
5733 left -= elem_len;
5734 ptr += (elem_len + 2);
5735 }
5736 return NULL;
5737}
5738
5739/*
5740 * FUNCTION: wlan_hdd_validate_operation_channel
5741 * called by wlan_hdd_cfg80211_start_bss() and
5742 * wlan_hdd_set_channel()
5743 * This function validates whether given channel is part of valid
5744 * channel list.
5745 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305746QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747 int channel)
5748{
5749
5750 uint32_t num_ch = 0;
5751 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5752 u32 indx = 0;
5753 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5754 uint8_t fValidChannel = false, count = 0;
5755 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
5756
5757 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5758
5759 if (hdd_pConfig_ini->sapAllowAllChannel) {
5760 /* Validate the channel */
5761 for (count = RF_CHAN_1; count <= RF_CHAN_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005762 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763 fValidChannel = true;
5764 break;
5765 }
5766 }
5767 if (fValidChannel != true) {
5768 hddLog(CDF_TRACE_LEVEL_ERROR,
5769 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305770 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771 }
5772 } else {
5773 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5774 valid_ch, &num_ch)) {
5775 hddLog(CDF_TRACE_LEVEL_ERROR,
5776 "%s: failed to get valid channel list",
5777 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305778 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 }
5780 for (indx = 0; indx < num_ch; indx++) {
5781 if (channel == valid_ch[indx]) {
5782 break;
5783 }
5784 }
5785
5786 if (indx >= num_ch) {
5787 hddLog(CDF_TRACE_LEVEL_ERROR,
5788 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305789 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790 }
5791 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305792 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005793
5794}
5795
5796#ifdef DHCP_SERVER_OFFLOAD
5797static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
5798{
5799 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
5800 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
5801 uint8_t numEntries = 0;
5802 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
5803 uint8_t num;
5804 uint32_t temp;
5805 pDhcpSrvInfo = cdf_mem_malloc(sizeof(*pDhcpSrvInfo));
5806 if (NULL == pDhcpSrvInfo) {
5807 hddLog(CDF_TRACE_LEVEL_ERROR,
5808 "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
5809 return;
5810 }
5811 cdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
5812 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
5813 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
5814 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
5815 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
5816 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
5817 if (numEntries != IPADDR_NUM_ENTRIES) {
5818 hddLog(CDF_TRACE_LEVEL_ERROR,
5819 "%s: incorrect IP address (%s) assigned for DHCP server!",
5820 __func__, pHddCtx->config->dhcpServerIP);
5821 goto end;
5822 }
5823 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
5824 hddLog(CDF_TRACE_LEVEL_ERROR,
5825 "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
5826 __func__, pHddCtx->config->dhcpServerIP);
5827 goto end;
5828 }
5829 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
5830 hddLog(CDF_TRACE_LEVEL_ERROR,
5831 "%s: invalid IP address (%s)! The last field must be less than 100!",
5832 __func__, pHddCtx->config->dhcpServerIP);
5833 goto end;
5834 }
5835 for (num = 0; num < numEntries; num++) {
5836 temp = srv_ip[num];
5837 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
5838 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305839 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005840 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
5841 hddLog(CDF_TRACE_LEVEL_ERROR,
5842 "%s: sme_setDHCPSrvOffload fail!", __func__);
5843 goto end;
5844 }
5845 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
5846 "%s: enable DHCP Server offload successfully!", __func__);
5847end:
5848 cdf_mem_free(pDhcpSrvInfo);
5849 return;
5850}
5851#endif /* DHCP_SERVER_OFFLOAD */
5852
5853static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
5854 struct net_device *dev,
5855 struct bss_parameters *params)
5856{
5857 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5858 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5859 int ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305860 QDF_STATUS cdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861
5862 ENTER();
5863
Anurag Chouhan6d760662016-02-20 16:05:43 +05305864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5866 return -EINVAL;
5867 }
5868
Anurag Chouhan6d760662016-02-20 16:05:43 +05305869 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
5871 pAdapter->sessionId, params->ap_isolate));
5872 hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"),
5873 hdd_device_mode_to_string(pAdapter->device_mode),
5874 pAdapter->device_mode, params->ap_isolate);
5875
5876 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5877 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305878 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005880
5881 if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP ||
5882 pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
5883 return -EOPNOTSUPP;
5884 }
5885
5886 /* ap_isolate == -1 means that in change bss, upper layer doesn't
5887 * want to update this parameter */
5888 if (-1 != params->ap_isolate) {
5889 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
5890 !!params->ap_isolate;
5891
5892 cdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
5893 pAdapter->sessionId,
5894 pAdapter->sessionCtx.
5895 ap.
5896 apDisableIntraBssFwd);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305897 if (!QDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 ret = -EINVAL;
5899 }
5900 }
5901
5902 EXIT();
5903 return ret;
5904}
5905
5906static int
5907wlan_hdd_change_iface_to_adhoc(struct net_device *ndev,
5908 tCsrRoamProfile *pRoamProfile,
5909 enum nl80211_iftype type)
5910{
5911 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5912 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5913 struct hdd_config *pConfig = pHddCtx->config;
5914 struct wireless_dev *wdev = ndev->ieee80211_ptr;
5915
5916 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
5917 pRoamProfile->phyMode =
5918 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
5919 pAdapter->device_mode = WLAN_HDD_IBSS;
5920 wdev->iftype = type;
5921
5922 return 0;
5923}
5924
5925static int wlan_hdd_change_iface_to_sta_mode(struct net_device *ndev,
5926 enum nl80211_iftype type)
5927{
5928 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5929 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5930 hdd_wext_state_t *wext;
5931 struct wireless_dev *wdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305932 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005933
5934 ENTER();
5935
5936 if (test_bit(ACS_IN_PROGRESS, &pHddCtx->g_event_flags)) {
5937 hddLog(LOG1, FL("ACS is in progress, don't change iface!"));
5938 return 0;
5939 }
5940
5941 wdev = ndev->ieee80211_ptr;
5942 hdd_stop_adapter(pHddCtx, pAdapter, true);
5943 hdd_deinit_adapter(pHddCtx, pAdapter, true);
5944 wdev->iftype = type;
5945 /*Check for sub-string p2p to confirm its a p2p interface */
5946 if (NULL != strnstr(ndev->name, "p2p", 3)) {
5947 pAdapter->device_mode =
5948 (type == NL80211_IFTYPE_STATION) ?
5949 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
5950 } else {
5951 pAdapter->device_mode =
5952 (type == NL80211_IFTYPE_STATION) ?
5953 WLAN_HDD_INFRA_STATION : WLAN_HDD_P2P_CLIENT;
5954 }
5955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005956 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
5957 hdd_set_station_ops(pAdapter->dev);
5958 status = hdd_init_station_mode(pAdapter);
5959 wext = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5960 wext->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata;
5961 wext->roamProfile.nAddIEScanLength =
5962 pAdapter->scan_info.scanAddIE.length;
5963 EXIT();
5964 return status;
5965}
5966
5967static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
5968 struct net_device *dev,
5969 struct bss_parameters *params)
5970{
5971 int ret;
5972
5973 cds_ssr_protect(__func__);
5974 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
5975 cds_ssr_unprotect(__func__);
5976
5977 return ret;
5978}
5979
5980/* FUNCTION: wlan_hdd_change_country_code_cd
5981 * to wait for contry code completion
5982 */
5983void *wlan_hdd_change_country_code_cb(void *pAdapter)
5984{
5985 hdd_adapter_t *call_back_pAdapter = pAdapter;
5986 complete(&call_back_pAdapter->change_country_code);
5987 return NULL;
5988}
5989
Rajeev Kumar98edb772016-01-19 12:42:19 -08005990/**
5991 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
5992 * @wiphy: Pointer to the wiphy structure
5993 * @ndev: Pointer to the net device
5994 * @type: Interface type
5995 * @flags: Flags for change interface
5996 * @params: Pointer to change interface parameters
5997 *
5998 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005999 */
6000static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6001 struct net_device *ndev,
6002 enum nl80211_iftype type,
6003 u32 *flags,
6004 struct vif_params *params)
6005{
6006 struct wireless_dev *wdev;
6007 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6008 hdd_context_t *pHddCtx;
6009 tCsrRoamProfile *pRoamProfile = NULL;
6010 eCsrRoamBssType LastBSSType;
6011 struct hdd_config *pConfig = NULL;
6012 eMib_dot11DesiredBssType connectedBssType;
6013 unsigned long rc;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306014 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 int status;
6016
6017 ENTER();
6018
Anurag Chouhan6d760662016-02-20 16:05:43 +05306019 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6021 return -EINVAL;
6022 }
6023
6024 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6025 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306026 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006027 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028
Anurag Chouhan6d760662016-02-20 16:05:43 +05306029 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
6031 pAdapter->sessionId, type));
6032
6033 hddLog(CDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"),
6034 pAdapter->device_mode, type);
6035
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006036 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006037 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
6038 0, HW_MODE_20_MHZ)) {
6039 hddLog(CDF_TRACE_LEVEL_DEBUG,
6040 FL("This concurrency combination is not allowed"));
6041 return -EINVAL;
6042 }
6043
6044 pConfig = pHddCtx->config;
6045 wdev = ndev->ieee80211_ptr;
6046
6047 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006048 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049
6050 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
6051
6052 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6053 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
Krunal Soni2c68f232015-10-26 20:52:51 -07006054 (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
6055 (pAdapter->device_mode == WLAN_HDD_IBSS)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056 hdd_wext_state_t *pWextState =
6057 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6058
6059 pRoamProfile = &pWextState->roamProfile;
6060 LastBSSType = pRoamProfile->BSSType;
6061
6062 switch (type) {
6063 case NL80211_IFTYPE_STATION:
6064 case NL80211_IFTYPE_P2P_CLIENT:
6065 vstatus = wlan_hdd_change_iface_to_sta_mode(ndev, type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306066 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067 return -EINVAL;
6068
6069 hdd_register_tx_flow_control(pAdapter,
6070 hdd_tx_resume_timer_expired_handler,
6071 hdd_tx_resume_cb);
6072
6073 goto done;
6074
6075 case NL80211_IFTYPE_ADHOC:
6076 wlan_hdd_tdls_exit(pAdapter);
Masti, Narayanraddi3d8690c2015-11-02 11:13:42 +05306077 hdd_deregister_tx_flow_control(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078 hddLog(LOG1, FL("Setting interface Type to ADHOC"));
6079 wlan_hdd_change_iface_to_adhoc(ndev, pRoamProfile,
6080 type);
6081 break;
6082
6083 case NL80211_IFTYPE_AP:
6084 case NL80211_IFTYPE_P2P_GO:
6085 {
6086 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
6087 FL("Setting interface Type to %s"),
6088 (type ==
6089 NL80211_IFTYPE_AP) ? "SoftAP" :
6090 "P2pGo");
6091
6092 /* Cancel any remain on channel for GO mode */
6093 if (NL80211_IFTYPE_P2P_GO == type) {
6094 wlan_hdd_cancel_existing_remain_on_channel
6095 (pAdapter);
6096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097 hdd_stop_adapter(pHddCtx, pAdapter, true);
6098
6099 /* De-init the adapter */
6100 hdd_deinit_adapter(pHddCtx, pAdapter, true);
6101 memset(&pAdapter->sessionCtx, 0,
6102 sizeof(pAdapter->sessionCtx));
6103 pAdapter->device_mode =
6104 (type ==
6105 NL80211_IFTYPE_AP) ? WLAN_HDD_SOFTAP :
6106 WLAN_HDD_P2P_GO;
6107
6108 /*
6109 * Fw will take care incase of concurrency
6110 */
6111
6112 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode)
6113 && (pConfig->apRandomBssidEnabled)) {
6114 /* To meet Android requirements create a randomized
6115 MAC address of the form 02:1A:11:Fx:xx:xx */
6116 get_random_bytes(&ndev->dev_addr[3], 3);
6117 ndev->dev_addr[0] = 0x02;
6118 ndev->dev_addr[1] = 0x1A;
6119 ndev->dev_addr[2] = 0x11;
6120 ndev->dev_addr[3] |= 0xF0;
6121 memcpy(pAdapter->macAddressCurrent.
6122 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306123 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006124 pr_info("wlan: Generated HotSpot BSSID "
6125 MAC_ADDRESS_STR "\n",
6126 MAC_ADDR_ARRAY(ndev->dev_addr));
6127 }
6128
6129 hdd_set_ap_ops(pAdapter->dev);
6130
6131 vstatus = hdd_init_ap_mode(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306132 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006133 hddLog(LOGP,
6134 FL
6135 ("Error initializing the ap mode"));
6136 return -EINVAL;
6137 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006138
6139 hdd_register_tx_flow_control(pAdapter,
6140 hdd_softap_tx_resume_timer_expired_handler,
6141 hdd_softap_tx_resume_cb);
6142
6143 /* Interface type changed update in wiphy structure */
6144 if (wdev) {
6145 wdev->iftype = type;
6146 } else {
6147 hddLog(LOGE,
6148 FL("Wireless dev is NULL"));
6149 return -EINVAL;
6150 }
6151 goto done;
6152 }
6153
6154 default:
6155 hddLog(LOGE, FL("Unsupported interface type (%d)"),
6156 type);
6157 return -EOPNOTSUPP;
6158 }
6159 } else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6160 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6161 switch (type) {
6162 case NL80211_IFTYPE_STATION:
6163 case NL80211_IFTYPE_P2P_CLIENT:
6164 case NL80211_IFTYPE_ADHOC:
6165 status = wlan_hdd_change_iface_to_sta_mode(ndev, type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306166 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006167 return status;
6168
6169 if ((NL80211_IFTYPE_P2P_CLIENT == type) ||
6170 (NL80211_IFTYPE_STATION == type)) {
6171
6172 hdd_register_tx_flow_control(pAdapter,
6173 hdd_tx_resume_timer_expired_handler,
6174 hdd_tx_resume_cb);
6175 }
6176 goto done;
6177
6178 case NL80211_IFTYPE_AP:
6179 case NL80211_IFTYPE_P2P_GO:
6180 wdev->iftype = type;
6181 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
6182 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
6183
6184 hdd_register_tx_flow_control(pAdapter,
6185 hdd_softap_tx_resume_timer_expired_handler,
6186 hdd_softap_tx_resume_cb);
6187 goto done;
6188
6189 default:
6190 hddLog(LOGE, FL("Unsupported interface type(%d)"),
6191 type);
6192 return -EOPNOTSUPP;
6193 }
6194 } else {
6195 hddLog(LOGE, FL("Unsupported device mode(%d)"),
6196 pAdapter->device_mode);
6197 return -EOPNOTSUPP;
6198 }
6199
6200 if (LastBSSType != pRoamProfile->BSSType) {
6201 /* Interface type changed update in wiphy structure */
6202 wdev->iftype = type;
6203
6204 /* The BSS mode changed, We need to issue disconnect
6205 if connected or in IBSS disconnect state */
6206 if (hdd_conn_get_connected_bss_type
6207 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType)
6208 || (eCSR_BSS_TYPE_START_IBSS == LastBSSType)) {
6209 /* Need to issue a disconnect to CSR. */
6210 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306211 if (QDF_STATUS_SUCCESS ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006212 sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
6213 pAdapter->sessionId,
6214 eCSR_DISCONNECT_REASON_UNSPECIFIED)) {
6215 rc = wait_for_completion_timeout(&pAdapter->
6216 disconnect_comp_var,
6217 msecs_to_jiffies
6218 (WLAN_WAIT_TIME_DISCONNECT));
6219 if (!rc) {
6220 hddLog(LOGE,
6221 FL
6222 ("Wait on disconnect_comp_var failed"));
6223 }
6224 }
6225 }
6226 }
6227
6228done:
6229 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006230 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006231
6232#ifdef WLAN_FEATURE_LPSS
6233 wlan_hdd_send_all_scan_intf_info(pHddCtx);
6234#endif
6235
6236 EXIT();
6237 return 0;
6238}
6239
Rajeev Kumar98edb772016-01-19 12:42:19 -08006240/**
6241 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6242 * @wiphy: Pointer to the wiphy structure
6243 * @ndev: Pointer to the net device
6244 * @type: Interface type
6245 * @flags: Flags for change interface
6246 * @params: Pointer to change interface parameters
6247 *
6248 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006249 */
6250static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6251 struct net_device *ndev,
6252 enum nl80211_iftype type,
6253 u32 *flags,
6254 struct vif_params *params)
6255{
6256 int ret;
6257
6258 cds_ssr_protect(__func__);
6259 ret =
6260 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
6261 cds_ssr_unprotect(__func__);
6262
6263 return ret;
6264}
6265
6266#ifdef FEATURE_WLAN_TDLS
6267static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
6268 int index, uint8_t match)
6269{
6270 int i;
6271 for (i = 0; i < index; i++) {
6272 if (arr[i] == match)
6273 return true;
6274 }
6275 return false;
6276}
6277#endif
6278
6279/**
6280 * __wlan_hdd_change_station() - change station
6281 * @wiphy: Pointer to the wiphy structure
6282 * @dev: Pointer to the net device.
6283 * @mac: bssid
6284 * @params: Pointer to station parameters
6285 *
6286 * Return: 0 for success, error number on failure.
6287 */
6288#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6289static int __wlan_hdd_change_station(struct wiphy *wiphy,
6290 struct net_device *dev,
6291 const uint8_t *mac,
6292 struct station_parameters *params)
6293#else
6294static int __wlan_hdd_change_station(struct wiphy *wiphy,
6295 struct net_device *dev,
6296 uint8_t *mac,
6297 struct station_parameters *params)
6298#endif
6299{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306300 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006301 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6302 hdd_context_t *pHddCtx;
6303 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306304 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006305#ifdef FEATURE_WLAN_TDLS
6306 tCsrStaParams StaParams = { 0 };
6307 uint8_t isBufSta = 0;
6308 uint8_t isOffChannelSupported = 0;
6309#endif
6310 int ret;
6311
6312 ENTER();
6313
Anurag Chouhan6d760662016-02-20 16:05:43 +05306314 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6316 return -EINVAL;
6317 }
6318
Anurag Chouhan6d760662016-02-20 16:05:43 +05306319 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006320 TRACE_CODE_HDD_CHANGE_STATION,
6321 pAdapter->sessionId, params->listen_interval));
6322
6323 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6324 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306325 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006326 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006327
6328 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6329
Anurag Chouhan6d760662016-02-20 16:05:43 +05306330 cdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006331
6332 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6333 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6334 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
6335 status =
6336 hdd_softap_change_sta_state(pAdapter,
6337 &STAMacAddress,
6338 ol_txrx_peer_state_auth);
6339
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306340 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006341 hddLog(CDF_TRACE_LEVEL_INFO,
6342 FL
6343 ("Not able to change TL state to AUTHENTICATED"));
6344 return -EINVAL;
6345 }
6346 }
6347 } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6348 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
6349#ifdef FEATURE_WLAN_TDLS
6350 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6351 StaParams.capability = params->capability;
6352 StaParams.uapsd_queues = params->uapsd_queues;
6353 StaParams.max_sp = params->max_sp;
6354
6355 /* Convert (first channel , number of channels) tuple to
6356 * the total list of channels. This goes with the assumption
6357 * that if the first channel is < 14, then the next channels
6358 * are an incremental of 1 else an incremental of 4 till the number
6359 * of channels.
6360 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306361 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006362 "%s: params->supported_channels_len: %d",
6363 __func__, params->supported_channels_len);
6364 if (0 != params->supported_channels_len) {
6365 int i = 0, j = 0, k = 0, no_of_channels = 0;
6366 int num_unique_channels;
6367 int next;
6368 for (i = 0;
6369 i < params->supported_channels_len
6370 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
6371 int wifi_chan_index;
6372 if (!wlan_hdd_is_duplicate_channel
6373 (StaParams.supported_channels, j,
6374 params->supported_channels[i])) {
6375 StaParams.
6376 supported_channels[j] =
6377 params->
6378 supported_channels[i];
6379 } else {
6380 continue;
6381 }
6382 wifi_chan_index =
6383 ((StaParams.supported_channels[j] <=
6384 HDD_CHANNEL_14) ? 1 : 4);
6385 no_of_channels =
6386 params->supported_channels[i + 1];
6387
Anurag Chouhan6d760662016-02-20 16:05:43 +05306388 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006389 CDF_TRACE_LEVEL_INFO,
6390 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d",
6391 __func__, i, j, k, j,
6392 StaParams.
6393 supported_channels[j],
6394 wifi_chan_index,
6395 no_of_channels);
6396 for (k = 1; k <= no_of_channels &&
6397 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
6398 k++) {
6399 next =
6400 StaParams.
6401 supported_channels[j] +
6402 wifi_chan_index;
6403 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
6404 StaParams.
6405 supported_channels[j
6406 +
6407 1]
6408 = next;
6409 } else {
6410 continue;
6411 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05306412 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006413 CDF_TRACE_LEVEL_INFO,
6414 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d",
6415 __func__, i, j, k,
6416 j + 1,
6417 StaParams.
6418 supported_channels[j +
6419 1]);
6420 j += 1;
6421 }
6422 }
6423 num_unique_channels = j + 1;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306424 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006425 CDF_TRACE_LEVEL_INFO,
6426 "%s: Unique Channel List", __func__);
6427 for (i = 0; i < num_unique_channels; i++) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306428 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006429 CDF_TRACE_LEVEL_INFO,
6430 "%s: StaParams.supported_channels[%d]: %d,",
6431 __func__, i,
6432 StaParams.
6433 supported_channels[i]);
6434 }
6435 if (MAX_CHANNEL < num_unique_channels)
6436 num_unique_channels = MAX_CHANNEL;
6437 StaParams.supported_channels_len =
6438 num_unique_channels;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306439 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006440 CDF_TRACE_LEVEL_INFO,
6441 "%s: After removing duplcates StaParams.supported_channels_len: %d",
6442 __func__,
6443 StaParams.supported_channels_len);
6444 }
6445 cdf_mem_copy(StaParams.supported_oper_classes,
6446 params->supported_oper_classes,
6447 params->supported_oper_classes_len);
6448 StaParams.supported_oper_classes_len =
6449 params->supported_oper_classes_len;
6450
6451 if (0 != params->ext_capab_len)
6452 cdf_mem_copy(StaParams.extn_capability,
6453 params->ext_capab,
6454 sizeof(StaParams.extn_capability));
6455
6456 if (NULL != params->ht_capa) {
6457 StaParams.htcap_present = 1;
6458 cdf_mem_copy(&StaParams.HTCap, params->ht_capa,
6459 sizeof(tSirHTCap));
6460 }
6461
6462 StaParams.supported_rates_len =
6463 params->supported_rates_len;
6464
6465 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
6466 * The supported_rates array , for all the structures propogating till Add Sta
6467 * to the firmware has to be modified , if the supplicant (ieee80211) is
6468 * modified to send more rates.
6469 */
6470
6471 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
6472 */
6473 if (StaParams.supported_rates_len >
6474 SIR_MAC_MAX_SUPP_RATES)
6475 StaParams.supported_rates_len =
6476 SIR_MAC_MAX_SUPP_RATES;
6477
6478 if (0 != StaParams.supported_rates_len) {
6479 int i = 0;
6480 cdf_mem_copy(StaParams.supported_rates,
6481 params->supported_rates,
6482 StaParams.supported_rates_len);
Anurag Chouhan6d760662016-02-20 16:05:43 +05306483 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006484 CDF_TRACE_LEVEL_INFO,
6485 "Supported Rates with Length %d",
6486 StaParams.supported_rates_len);
6487 for (i = 0; i < StaParams.supported_rates_len;
6488 i++)
Anurag Chouhan6d760662016-02-20 16:05:43 +05306489 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006490 CDF_TRACE_LEVEL_INFO,
6491 "[%d]: %0x", i,
6492 StaParams.supported_rates[i]);
6493 }
6494
6495 if (NULL != params->vht_capa) {
6496 StaParams.vhtcap_present = 1;
6497 cdf_mem_copy(&StaParams.VHTCap,
6498 params->vht_capa,
6499 sizeof(tSirVHTCap));
6500 }
6501
6502 if (0 != params->ext_capab_len) {
6503 /*Define A Macro : TODO Sunil */
6504 if ((1 << 4) & StaParams.extn_capability[3]) {
6505 isBufSta = 1;
6506 }
6507 /* TDLS Channel Switching Support */
6508 if ((1 << 6) & StaParams.extn_capability[3]) {
6509 isOffChannelSupported = 1;
6510 }
6511 }
6512
6513 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
6514 &StaParams,
6515 isBufSta,
6516 isOffChannelSupported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306517 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006518 hddLog(CDF_TRACE_LEVEL_ERROR,
6519 FL
6520 ("wlan_hdd_tdls_set_peer_caps failed!"));
6521 return -EINVAL;
6522 }
6523
6524 status =
6525 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
6526 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306527 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006528 hddLog(CDF_TRACE_LEVEL_ERROR,
6529 FL("wlan_hdd_tdls_add_station failed!"));
6530 return -EINVAL;
6531 }
6532 }
6533#endif
6534 }
6535 EXIT();
6536 return ret;
6537}
6538
6539/**
6540 * wlan_hdd_change_station() - cfg80211 change station handler function
6541 * @wiphy: Pointer to the wiphy structure
6542 * @dev: Pointer to the net device.
6543 * @mac: bssid
6544 * @params: Pointer to station parameters
6545 *
6546 * This is the cfg80211 change station handler function which invokes
6547 * the internal function @__wlan_hdd_change_station with
6548 * SSR protection.
6549 *
6550 * Return: 0 for success, error number on failure.
6551 */
6552#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
6553static int wlan_hdd_change_station(struct wiphy *wiphy,
6554 struct net_device *dev,
6555 const u8 *mac,
6556 struct station_parameters *params)
6557#else
6558static int wlan_hdd_change_station(struct wiphy *wiphy,
6559 struct net_device *dev,
6560 u8 *mac,
6561 struct station_parameters *params)
6562#endif
6563{
6564 int ret;
6565
6566 cds_ssr_protect(__func__);
6567 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
6568 cds_ssr_unprotect(__func__);
6569
6570 return ret;
6571}
6572
6573/*
6574 * FUNCTION: __wlan_hdd_cfg80211_add_key
6575 * This function is used to initialize the key information
6576 */
6577static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6578 struct net_device *ndev,
6579 u8 key_index, bool pairwise,
6580 const u8 *mac_addr,
6581 struct key_params *params)
6582{
6583 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6584 tCsrRoamSetKey setKey;
6585 int status;
6586 uint32_t roamId = 0xFF;
6587#ifndef WLAN_FEATURE_MBSSID
6588 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context;
6589#endif
6590 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306591 QDF_STATUS cdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006592 hdd_context_t *pHddCtx;
6593 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6594
6595 ENTER();
6596
Anurag Chouhan6d760662016-02-20 16:05:43 +05306597 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006598 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6599 return -EINVAL;
6600 }
6601
Anurag Chouhan6d760662016-02-20 16:05:43 +05306602 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006603 TRACE_CODE_HDD_CFG80211_ADD_KEY,
6604 pAdapter->sessionId, params->key_len));
6605 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6606 status = wlan_hdd_validate_context(pHddCtx);
6607
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306608 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006609 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006610
6611 hddLog(LOG1, FL("Device_mode %s(%d)"),
6612 hdd_device_mode_to_string(pAdapter->device_mode),
6613 pAdapter->device_mode);
6614
6615 if (CSR_MAX_NUM_KEY <= key_index) {
6616 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d",
6617 __func__, key_index);
6618
6619 return -EINVAL;
6620 }
6621
6622 if (CSR_MAX_KEY_LEN < params->key_len) {
6623 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d",
6624 __func__, params->key_len);
6625
6626 return -EINVAL;
6627 }
6628
6629 hddLog(CDF_TRACE_LEVEL_INFO,
6630 "%s: called with key index = %d & key length %d",
6631 __func__, key_index, params->key_len);
6632
6633 /*extract key idx, key len and key */
6634 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
6635 setKey.keyId = key_index;
6636 setKey.keyLength = params->key_len;
6637 cdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
6638
6639 switch (params->cipher) {
6640 case WLAN_CIPHER_SUITE_WEP40:
6641 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6642 break;
6643
6644 case WLAN_CIPHER_SUITE_WEP104:
6645 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
6646 break;
6647
6648 case WLAN_CIPHER_SUITE_TKIP:
6649 {
6650 u8 *pKey = &setKey.Key[0];
6651 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
6652
6653 cdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
6654
6655 /*Supplicant sends the 32bytes key in this order
6656
6657 |--------------|----------|----------|
6658 | Tk1 |TX-MIC | RX Mic |
6659 |||--------------|----------|----------|
6660 <---16bytes---><--8bytes--><--8bytes-->
6661
6662 */
6663 /*Sme expects the 32 bytes key to be in the below order
6664
6665 |--------------|----------|----------|
6666 | Tk1 |RX-MIC | TX Mic |
6667 |||--------------|----------|----------|
6668 <---16bytes---><--8bytes--><--8bytes-->
6669 */
6670 /* Copy the Temporal Key 1 (TK1) */
6671 cdf_mem_copy(pKey, params->key, 16);
6672
6673 /*Copy the rx mic first */
6674 cdf_mem_copy(&pKey[16], &params->key[24], 8);
6675
6676 /*Copy the tx mic */
6677 cdf_mem_copy(&pKey[24], &params->key[16], 8);
6678
6679 break;
6680 }
6681
6682 case WLAN_CIPHER_SUITE_CCMP:
6683 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
6684 break;
6685
6686#ifdef FEATURE_WLAN_WAPI
6687 case WLAN_CIPHER_SUITE_SMS4:
6688 {
6689 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
6690 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
6691 mac_addr, params->key,
6692 params->key_len);
6693 return 0;
6694 }
6695#endif
6696
6697#ifdef FEATURE_WLAN_ESE
6698 case WLAN_CIPHER_SUITE_KRK:
6699 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
6700 break;
6701#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6702 case WLAN_CIPHER_SUITE_BTK:
6703 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
6704 break;
6705#endif
6706#endif
6707
6708#ifdef WLAN_FEATURE_11W
6709 case WLAN_CIPHER_SUITE_AES_CMAC:
6710 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
6711 break;
6712#endif
6713
6714 default:
6715 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
6716 __func__, params->cipher);
6717 return -EOPNOTSUPP;
6718 }
6719
6720 hddLog(CDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
6721 __func__, setKey.encType);
6722
6723 if (!pairwise) {
6724 /* set group key */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306725 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006726 "%s- %d: setting Broadcast key", __func__, __LINE__);
6727 setKey.keyDirection = eSIR_RX_ONLY;
6728 cdf_set_macaddr_broadcast(&setKey.peerMac);
6729 } else {
6730 /* set pairwise key */
Anurag Chouhan6d760662016-02-20 16:05:43 +05306731 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006732 "%s- %d: setting pairwise key", __func__, __LINE__);
6733 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306734 cdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006735 }
6736 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise) {
6737 /* if a key is already installed, block all subsequent ones */
6738 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
6739 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6740 "%s: IBSS key installed already", __func__);
6741 return 0;
6742 }
6743
6744 setKey.keyDirection = eSIR_TX_RX;
6745 /*Set the group key */
6746 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6747 pAdapter->sessionId, &setKey, &roamId);
6748
6749 if (0 != status) {
6750 hddLog(CDF_TRACE_LEVEL_ERROR,
6751 "%s: sme_roam_set_key failed, returned %d",
6752 __func__, status);
6753 return -EINVAL;
6754 }
6755 /*Save the keys here and call sme_roam_set_key for setting
6756 the PTK after peer joins the IBSS network */
6757 cdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
6758 &setKey, sizeof(tCsrRoamSetKey));
6759
6760 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
6761 return status;
6762 }
6763 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6764 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6765 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6766 if (pHostapdState->bssState == BSS_START) {
6767#ifdef WLAN_FEATURE_MBSSID
6768 status =
6769 wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR
6770 (pAdapter), &setKey);
6771#else
6772 status = wlansap_set_key_sta(p_cds_context, &setKey);
6773#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306774 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306775 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006776 CDF_TRACE_LEVEL_ERROR,
6777 "[%4d] wlansap_set_key_sta returned ERROR status= %d",
6778 __LINE__, status);
6779 }
6780 }
6781
6782 /* Save the key in ap ctx for use on START_BASS and restart */
6783 if (pairwise ||
6784 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
6785 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
6786 cdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
6787 sizeof(tCsrRoamSetKey));
6788 else
6789 cdf_mem_copy(&ap_ctx->groupKey, &setKey,
6790 sizeof(tCsrRoamSetKey));
6791
6792 } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6793 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
6794 hdd_wext_state_t *pWextState =
6795 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6796 hdd_station_ctx_t *pHddStaCtx =
6797 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6798
6799 if (!pairwise) {
6800 /* set group key */
6801 if (pHddStaCtx->roam_info.deferKeyComplete) {
Anurag Chouhan6d760662016-02-20 16:05:43 +05306802 CDF_TRACE(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006803 CDF_TRACE_LEVEL_INFO,
6804 "%s- %d: Perform Set key Complete",
6805 __func__, __LINE__);
6806 hdd_perform_roam_set_key_complete(pAdapter);
6807 }
6808 }
6809
6810 pWextState->roamProfile.Keys.KeyLength[key_index] =
6811 (u8) params->key_len;
6812
6813 pWextState->roamProfile.Keys.defaultIndex = key_index;
6814
6815 cdf_mem_copy(&pWextState->roamProfile.Keys.
6816 KeyMaterial[key_index][0], params->key,
6817 params->key_len);
6818
6819 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6820
6821 hddLog(LOG2,
6822 FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"),
6823 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6824 setKey.keyDirection);
6825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006826 /* The supplicant may attempt to set the PTK once pre-authentication
6827 is done. Save the key in the UMAC and include it in the ADD BSS
6828 request */
6829 cdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6830 pAdapter->sessionId, &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306831 if (cdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006832 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6833 "%s: Update PreAuth Key success", __func__);
6834 return 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306835 } else if (cdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006836 hddLog(CDF_TRACE_LEVEL_ERROR,
6837 "%s: Update PreAuth Key failed", __func__);
6838 return -EINVAL;
6839 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006840
6841 /* issue set key request to SME */
6842 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6843 pAdapter->sessionId, &setKey, &roamId);
6844
6845 if (0 != status) {
6846 hddLog(CDF_TRACE_LEVEL_ERROR,
6847 "%s: sme_roam_set_key failed, returned %d",
6848 __func__, status);
6849 pHddStaCtx->roam_info.roamingState =
6850 HDD_ROAM_STATE_NONE;
6851 return -EINVAL;
6852 }
6853
6854 /* in case of IBSS as there was no information available about WEP keys during
6855 * IBSS join, group key intialized with NULL key, so re-initialize group key
6856 * with correct value*/
6857 if ((eCSR_BSS_TYPE_START_IBSS ==
6858 pWextState->roamProfile.BSSType)
6859 &&
6860 !((IW_AUTH_KEY_MGMT_802_1X ==
6861 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
6862 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
6863 pHddStaCtx->conn_info.authType)
6864 )
6865 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
6866 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
6867 )
6868 ) {
6869 setKey.keyDirection = eSIR_RX_ONLY;
6870 cdf_set_macaddr_broadcast(&setKey.peerMac);
6871
6872 hddLog(LOG2,
6873 FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"),
6874 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6875 setKey.keyDirection);
6876
6877 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6878 pAdapter->sessionId, &setKey,
6879 &roamId);
6880
6881 if (0 != status) {
6882 hddLog(CDF_TRACE_LEVEL_ERROR,
6883 "%s: sme_roam_set_key failed for group key (IBSS), returned %d",
6884 __func__, status);
6885 pHddStaCtx->roam_info.roamingState =
6886 HDD_ROAM_STATE_NONE;
6887 return -EINVAL;
6888 }
6889 }
6890 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306891 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006892 return 0;
6893}
6894
6895static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6896 struct net_device *ndev,
6897 u8 key_index, bool pairwise,
6898 const u8 *mac_addr,
6899 struct key_params *params)
6900{
6901 int ret;
6902 cds_ssr_protect(__func__);
6903 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
6904 mac_addr, params);
6905 cds_ssr_unprotect(__func__);
6906
6907 return ret;
6908}
6909
6910/*
6911 * FUNCTION: __wlan_hdd_cfg80211_get_key
6912 * This function is used to get the key information
6913 */
6914static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
6915 struct net_device *ndev,
6916 u8 key_index, bool pairwise,
6917 const u8 *mac_addr, void *cookie,
6918 void (*callback)(void *cookie,
6919 struct key_params *)
6920 )
6921{
6922 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6923 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6924 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
6925 struct key_params params;
6926
6927 ENTER();
6928
Anurag Chouhan6d760662016-02-20 16:05:43 +05306929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006930 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6931 return -EINVAL;
6932 }
6933
6934 hddLog(LOG1, FL("Device_mode %s(%d)"),
6935 hdd_device_mode_to_string(pAdapter->device_mode),
6936 pAdapter->device_mode);
6937
6938 memset(&params, 0, sizeof(params));
6939
6940 if (CSR_MAX_NUM_KEY <= key_index) {
6941 hddLog(CDF_TRACE_LEVEL_ERROR, FL("invalid key index %d"),
6942 key_index);
6943 return -EINVAL;
6944 }
6945
6946 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
6947 case eCSR_ENCRYPT_TYPE_NONE:
6948 params.cipher = IW_AUTH_CIPHER_NONE;
6949 break;
6950
6951 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
6952 case eCSR_ENCRYPT_TYPE_WEP40:
6953 params.cipher = WLAN_CIPHER_SUITE_WEP40;
6954 break;
6955
6956 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
6957 case eCSR_ENCRYPT_TYPE_WEP104:
6958 params.cipher = WLAN_CIPHER_SUITE_WEP104;
6959 break;
6960
6961 case eCSR_ENCRYPT_TYPE_TKIP:
6962 params.cipher = WLAN_CIPHER_SUITE_TKIP;
6963 break;
6964
6965 case eCSR_ENCRYPT_TYPE_AES:
6966 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6967 break;
6968
6969 default:
6970 params.cipher = IW_AUTH_CIPHER_NONE;
6971 break;
6972 }
6973
Anurag Chouhan6d760662016-02-20 16:05:43 +05306974 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006975 TRACE_CODE_HDD_CFG80211_GET_KEY,
6976 pAdapter->sessionId, params.cipher));
6977
6978 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
6979 params.seq_len = 0;
6980 params.seq = NULL;
6981 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
6982 callback(cookie, &params);
6983
6984 EXIT();
6985 return 0;
6986}
6987
6988static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
6989 struct net_device *ndev,
6990 u8 key_index, bool pairwise,
6991 const u8 *mac_addr, void *cookie,
6992 void (*callback)(void *cookie,
6993 struct key_params *)
6994 )
6995{
6996 int ret;
6997
6998 cds_ssr_protect(__func__);
6999 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
7000 mac_addr, cookie, callback);
7001 cds_ssr_unprotect(__func__);
7002
7003 return ret;
7004}
7005
7006/**
7007 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
7008 * @wiphy: wiphy interface context
7009 * @ndev: pointer to net device
7010 * @key_index: Key index used in 802.11 frames
7011 * @unicast: true if it is unicast key
7012 * @multicast: true if it is multicast key
7013 *
7014 * This function is required for cfg80211_ops API.
7015 * It is used to delete the key information
7016 * Underlying hardware implementation does not have API to delete the
7017 * encryption key. It is automatically deleted when the peer is
7018 * removed. Hence this function currently does nothing.
7019 * Future implementation may interprete delete key operation to
7020 * replacing the key with a random junk value, effectively making it
7021 * useless.
7022 *
7023 * Return: status code, always 0.
7024 */
7025
7026static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7027 struct net_device *ndev,
7028 u8 key_index,
7029 bool pairwise, const u8 *mac_addr)
7030{
7031 EXIT();
7032 return 0;
7033}
7034
7035/**
7036 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
7037 * @wiphy: Pointer to wiphy structure.
7038 * @dev: Pointer to net_device structure.
7039 * @key_index: key index
7040 * @pairwise: pairwise
7041 * @mac_addr: mac address
7042 *
7043 * This is the cfg80211 delete key handler function which invokes
7044 * the internal function @__wlan_hdd_cfg80211_del_key with
7045 * SSR protection.
7046 *
7047 * Return: 0 for success, error number on failure.
7048 */
7049static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7050 struct net_device *dev,
7051 u8 key_index,
7052 bool pairwise, const u8 *mac_addr)
7053{
7054 int ret;
7055
7056 cds_ssr_protect(__func__);
7057 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
7058 pairwise, mac_addr);
7059 cds_ssr_unprotect(__func__);
7060
7061 return ret;
7062}
7063
7064/*
7065 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
7066 * This function is used to set the default tx key index
7067 */
7068static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7069 struct net_device *ndev,
7070 u8 key_index,
7071 bool unicast, bool multicast)
7072{
7073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7074 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7075 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7076 hdd_context_t *pHddCtx;
7077 int status;
7078
7079 ENTER();
7080
Anurag Chouhan6d760662016-02-20 16:05:43 +05307081 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007082 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7083 return -EINVAL;
7084 }
7085
Anurag Chouhan6d760662016-02-20 16:05:43 +05307086 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007087 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
7088 pAdapter->sessionId, key_index));
7089
7090 hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"),
7091 hdd_device_mode_to_string(pAdapter->device_mode),
7092 pAdapter->device_mode, key_index);
7093
7094 if (CSR_MAX_NUM_KEY <= key_index) {
7095 hddLog(LOGE, FL("Invalid key index %d"), key_index);
7096 return -EINVAL;
7097 }
7098
7099 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7100 status = wlan_hdd_validate_context(pHddCtx);
7101
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307102 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007103 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007104
7105 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
7106 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
7107 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7108 pHddStaCtx->conn_info.ucEncryptionType) &&
7109 (eCSR_ENCRYPT_TYPE_AES !=
7110 pHddStaCtx->conn_info.ucEncryptionType)) {
7111 /* If default key index is not same as previous one,
7112 * then update the default key index */
7113
7114 tCsrRoamSetKey setKey;
7115 uint32_t roamId = 0xFF;
7116 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
7117
7118 hddLog(LOG2, FL("Default tx key index %d"), key_index);
7119
7120 Keys->defaultIndex = (u8) key_index;
7121 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
7122 setKey.keyId = key_index;
7123 setKey.keyLength = Keys->KeyLength[key_index];
7124
7125 cdf_mem_copy(&setKey.Key[0],
7126 &Keys->KeyMaterial[key_index][0],
7127 Keys->KeyLength[key_index]);
7128
7129 setKey.keyDirection = eSIR_TX_RX;
7130
7131 cdf_copy_macaddr(&setKey.peerMac,
7132 &pHddStaCtx->conn_info.bssId);
7133
7134 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
7135 pWextState->roamProfile.EncryptionType.
7136 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
7137 /* In the case of dynamic wep supplicant hardcodes DWEP type
7138 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
7139 * WEP-40 encryption. In this canse the key length is 5 but the
7140 * encryption type is 104 hence checking the key langht(5) and
7141 * encryption type(104) and switching encryption type to 40*/
7142 pWextState->roamProfile.EncryptionType.
7143 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7144 pWextState->roamProfile.mcEncryptionType.
7145 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7146 }
7147
7148 setKey.encType =
7149 pWextState->roamProfile.EncryptionType.
7150 encryptionType[0];
7151
7152 /* Issue set key request */
7153 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7154 pAdapter->sessionId, &setKey,
7155 &roamId);
7156
7157 if (0 != status) {
7158 hddLog(LOGE,
7159 FL("sme_roam_set_key failed, returned %d"),
7160 status);
7161 return -EINVAL;
7162 }
7163 }
7164 } else if (WLAN_HDD_SOFTAP == pAdapter->device_mode) {
7165 /* In SoftAp mode setting key direction for default mode */
7166 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7167 pWextState->roamProfile.EncryptionType.encryptionType[0])
7168 && (eCSR_ENCRYPT_TYPE_AES !=
7169 pWextState->roamProfile.EncryptionType.
7170 encryptionType[0])) {
7171 /* Saving key direction for default key index to TX default */
7172 hdd_ap_ctx_t *pAPCtx =
7173 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7174 pAPCtx->wepKey[key_index].keyDirection =
7175 eSIR_TX_DEFAULT;
7176 }
7177 }
7178
7179 EXIT();
7180 return status;
7181}
7182
7183static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7184 struct net_device *ndev,
7185 u8 key_index,
7186 bool unicast, bool multicast)
7187{
7188 int ret;
7189 cds_ssr_protect(__func__);
7190 ret =
7191 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
7192 multicast);
7193 cds_ssr_unprotect(__func__);
7194
7195 return ret;
7196}
7197
7198/**
7199 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
7200 * @pAdapter: Pointer to adapter
7201 * @pRoamInfo: Pointer to roam info
7202 *
7203 * Return: struct cfg80211_bss pointer
7204 */
7205struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
7206 tCsrRoamInfo *pRoamInfo)
7207{
7208 struct net_device *dev = pAdapter->dev;
7209 struct wireless_dev *wdev = dev->ieee80211_ptr;
7210 struct wiphy *wiphy = wdev->wiphy;
7211 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
7212 int chan_no;
7213 unsigned int freq;
7214 struct ieee80211_channel *chan;
7215 struct cfg80211_bss *bss = NULL;
7216
7217 ENTER();
7218
7219 if (NULL == pBssDesc) {
7220 hddLog(LOGE, FL("pBssDesc is NULL"));
7221 return bss;
7222 }
7223
7224 if (NULL == pRoamInfo->pProfile) {
7225 hddLog(LOGE, FL("Roam profile is NULL"));
7226 return bss;
7227 }
7228
7229 chan_no = pBssDesc->channelId;
7230
7231 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
7232 freq =
7233 ieee80211_channel_to_frequency(chan_no,
7234 IEEE80211_BAND_2GHZ);
7235 } else {
7236 freq =
7237 ieee80211_channel_to_frequency(chan_no,
7238 IEEE80211_BAND_5GHZ);
7239 }
7240
7241 chan = __ieee80211_get_channel(wiphy, freq);
7242
7243 if (!chan) {
7244 hddLog(LOGE, FL("chan pointer is NULL"));
7245 return NULL;
7246 }
7247
7248 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
7249 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
7250 ssId[0],
7251 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
Ryan Hsu535d16a2016-01-18 16:45:12 -08007252#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007253 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
Ryan Hsu535d16a2016-01-18 16:45:12 -08007254#else
7255 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
7256#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007257 if (bss == NULL) {
7258 hddLog(LOGE, FL("BSS not present"));
7259 } else {
7260 hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID "
7261 MAC_ADDRESS_STR),
7262 MAC_ADDR_ARRAY(pBssDesc->bssId));
7263 cfg80211_unlink_bss(wiphy, bss);
7264 }
7265 return bss;
7266}
7267
7268/**
7269 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
7270 * @pAdapter: Pointer to adapter
7271 * @bss_desc: Pointer to bss descriptor
7272 *
7273 * This function is used to inform the BSS details to nl80211 interface.
7274 *
7275 * Return: struct cfg80211_bss pointer
7276 */
7277static struct cfg80211_bss *
7278wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
7279 tSirBssDescription *bss_desc)
7280{
7281 /*
7282 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
7283 * already exists in bss data base of cfg80211 for that particular BSS
7284 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
7285 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
7286 * As of now there is no possibility to get the mgmt(probe response)
7287 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
7288 * and passing to cfg80211_inform_bss_frame.
7289 */
7290 struct net_device *dev = pAdapter->dev;
7291 struct wireless_dev *wdev = dev->ieee80211_ptr;
7292 struct wiphy *wiphy = wdev->wiphy;
7293 int chan_no = bss_desc->channelId;
7294#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7295 qcom_ie_age *qie_age = NULL;
7296 int ie_length =
7297 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
7298#else
7299 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
7300#endif
7301 const char *ie =
7302 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
7303 unsigned int freq;
7304 struct ieee80211_channel *chan;
7305 struct ieee80211_mgmt *mgmt = NULL;
7306 struct cfg80211_bss *bss_status = NULL;
7307 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
7308 int rssi = 0;
7309 hdd_context_t *pHddCtx;
7310 int status;
7311#ifdef CONFIG_CNSS
7312 struct timespec ts;
7313#endif
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007314 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007315
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307316 ENTER();
7317
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007318 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7319 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307320 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007321 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007322
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007323 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007324 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
7325 if (!mgmt) {
7326 hddLog(LOGE, FL("memory allocation failed"));
7327 return NULL;
7328 }
7329
7330 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
7331
7332#ifdef CONFIG_CNSS
7333 /* Android does not want the timestamp from the frame.
7334 Instead it wants a monotonic increasing value */
7335 cnss_get_monotonic_boottime(&ts);
7336 mgmt->u.probe_resp.timestamp =
7337 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
7338#else
7339 /* keep old behavior for non-open source (for now) */
7340 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
7341 sizeof(bss_desc->timeStamp));
7342
7343#endif
7344
7345 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
7346 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
7347
7348#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7349 /* GPS Requirement: need age ie per entry. Using vendor specific. */
7350 /* Assuming this is the last IE, copy at the end */
7351 ie_length -= sizeof(qcom_ie_age);
7352 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
7353 qie_age->element_id = QCOM_VENDOR_IE_ID;
7354 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
7355 qie_age->oui_1 = QCOM_OUI1;
7356 qie_age->oui_2 = QCOM_OUI2;
7357 qie_age->oui_3 = QCOM_OUI3;
7358 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
7359 qie_age->age =
7360 cdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
7361 qie_age->tsf_delta = bss_desc->tsf_delta;
7362#endif
7363
7364 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
7365 if (bss_desc->fProbeRsp) {
7366 mgmt->frame_control |=
7367 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
7368 } else {
7369 mgmt->frame_control |=
7370 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
7371 }
7372
7373 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
7374 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
7375 freq =
7376 ieee80211_channel_to_frequency(chan_no,
7377 IEEE80211_BAND_2GHZ);
7378 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
7379 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
7380 freq =
7381 ieee80211_channel_to_frequency(chan_no,
7382 IEEE80211_BAND_5GHZ);
7383 } else {
7384 hddLog(LOGE, FL("Invalid chan_no %d"), chan_no);
7385 kfree(mgmt);
7386 return NULL;
7387 }
7388
7389 chan = __ieee80211_get_channel(wiphy, freq);
7390 /* When the band is changed on the fly using the GUI, three things are done
7391 * 1. scan abort
7392 * 2. flush scan results from cache
7393 * 3. update the band with the new band user specified (refer to the
7394 * hdd_set_band_helper function) as part of the scan abort, message will be
7395 * queued to PE and we proceed with flushing and changinh the band.
7396 * PE will stop the scanning further and report back the results what ever
7397 * it had till now by calling the call back function.
7398 * if the time between update band and scandone call back is sufficient
7399 * enough the band change reflects in SME, SME validates the channels
7400 * and discards the channels correponding to previous band and calls back
7401 * with zero bss results. but if the time between band update and scan done
7402 * callback is very small then band change will not reflect in SME and SME
7403 * reports to HDD all the channels correponding to previous band.this is due
7404 * to race condition.but those channels are invalid to the new band and so
7405 * this function __ieee80211_get_channel will return NULL.Each time we
7406 * report scan result with this pointer null warning kernel trace is printed.
7407 * if the scan results contain large number of APs continuosly kernel
7408 * warning trace is printed and it will lead to apps watch dog bark.
7409 * So drop the bss and continue to next bss.
7410 */
7411 if (chan == NULL) {
7412 hddLog(LOGE, FL("chan pointer is NULL"));
7413 kfree(mgmt);
7414 return NULL;
7415 }
7416
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007417 /* Based on .ini configuration, raw rssi can be reported for bss.
7418 * Raw rssi is typically used for estimating power.
7419 */
7420
7421 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
7422 bss_desc->rssi;
7423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007424 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +05307425 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007426
7427 hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"),
7428 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
7429 (int)(rssi / 100));
7430
7431 bss_status =
7432 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
7433 GFP_KERNEL);
7434 kfree(mgmt);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307435 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007436 return bss_status;
7437}
7438
7439/**
7440 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
7441 * @pAdapter: Pointer to adapter
7442 * @pRoamInfo: Pointer to roam info
7443 *
7444 * This function is used to update the BSS data base of CFG8011
7445 *
7446 * Return: struct cfg80211_bss pointer
7447 */
7448struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
7449 tCsrRoamInfo *pRoamInfo)
7450{
7451 tCsrRoamConnectedProfile roamProfile;
7452 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7453 struct cfg80211_bss *bss = NULL;
7454
7455 ENTER();
7456
7457 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
7458 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
7459
7460 if (NULL != roamProfile.pBssDesc) {
7461 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7462 roamProfile.pBssDesc);
7463
7464 if (NULL == bss)
7465 hddLog(LOG1,
7466 FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL"));
7467
Naveen Rawatdf0a7e72016-01-06 18:35:53 -08007468 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007469 } else {
7470 hddLog(LOGE, FL("roamProfile.pBssDesc is NULL"));
7471 }
7472 EXIT();
7473 return bss;
7474}
7475/**
7476 * wlan_hdd_cfg80211_update_bss() - update bss
7477 * @wiphy: Pointer to wiphy
7478 * @pAdapter: Pointer to adapter
7479 * @scan_time: scan request timestamp
7480 *
7481 * Return: zero if success, non-zero otherwise
7482 */
7483int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
7484 hdd_adapter_t *pAdapter,
7485 uint32_t scan_time)
7486{
7487 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7488 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307489 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007490 tScanResultHandle pResult;
7491 struct cfg80211_bss *bss_status = NULL;
7492 hdd_context_t *pHddCtx;
7493 int ret;
7494
7495 ENTER();
7496
Anurag Chouhan6d760662016-02-20 16:05:43 +05307497 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007498 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
7499 NO_SESSION, pAdapter->sessionId));
7500
7501 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7502 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307503 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007504 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007505
7506 /* start getting scan results and populate cgf80211 BSS database */
7507 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
7508
7509 /* no scan results */
7510 if (NULL == pResult) {
7511 hddLog(LOGE, FL("No scan result Status %d"), status);
7512 return status;
7513 }
7514
7515 pScanResult = sme_scan_result_get_first(hHal, pResult);
7516
7517 while (pScanResult) {
7518 /*
7519 * - cfg80211_inform_bss() is not updating ie field of bss
7520 * entry if entry already exists in bss data base of cfg80211
7521 * for that particular BSS ID. Using cfg80211_inform_bss_frame
7522 * to update thebss entry instead of cfg80211_inform_bss,
7523 * But this call expects mgmt packet as input. As of now
7524 * there is no possibility to get the mgmt(probe response)
7525 * frame from PE, converting bss_desc to
7526 * ieee80211_mgmt(probe response) and passing to c
7527 * fg80211_inform_bss_frame.
7528 * - Update BSS only if beacon timestamp is later than
7529 * scan request timestamp.
7530 */
7531 if ((scan_time == 0) ||
7532 (scan_time <
7533 pScanResult->BssDescriptor.nReceivedTime)) {
7534 bss_status =
7535 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7536 &pScanResult->BssDescriptor);
7537
7538 if (NULL == bss_status) {
7539 hdd_info("NULL returned by cfg80211_inform_bss_frame");
7540 } else {
7541 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007542 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007543 bss_status);
7544 }
7545 } else {
7546 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
7547 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
7548 }
7549 pScanResult = sme_scan_result_get_next(hHal, pResult);
7550 }
7551
7552 sme_scan_result_purge(hHal, pResult);
7553 /*
7554 * For SAP mode, scan is invoked by hostapd during SAP start
7555 * if hostapd is restarted, we need to flush previous scan
7556 * result so that it will reflect environment change
7557 */
7558 if (pAdapter->device_mode == WLAN_HDD_SOFTAP
7559#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
7560 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
7561#endif
7562 )
7563 sme_scan_flush_result(hHal);
7564
7565 EXIT();
7566 return 0;
7567}
7568
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007569/**
7570 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
7571 * @pAdapter: Pointer to adapter
7572 * @pRoamInfo: Pointer to roam info
7573 * @index: Index
7574 * @preauth: Preauth flag
7575 *
7576 * This function is used to notify the supplicant of a new PMKSA candidate.
7577 *
7578 * Return: 0 for success, non-zero for failure
7579 */
7580int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
7581 tCsrRoamInfo *pRoamInfo,
7582 int index, bool preauth)
7583{
7584#ifdef FEATURE_WLAN_OKC
7585 struct net_device *dev = pAdapter->dev;
7586 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
7587
7588 ENTER();
7589 hddLog(LOG1, FL("is going to notify supplicant of:"));
7590
7591 if (NULL == pRoamInfo) {
7592 hddLog(LOGP, FL("pRoamInfo is NULL"));
7593 return -EINVAL;
7594 }
7595
7596 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
7597 hddLog(LOG1, MAC_ADDRESS_STR,
7598 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
7599 cfg80211_pmksa_candidate_notify(dev, index,
7600 pRoamInfo->bssid.bytes,
7601 preauth, GFP_KERNEL);
7602 }
7603#endif /* FEATURE_WLAN_OKC */
7604 return 0;
7605}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007606
7607#ifdef FEATURE_WLAN_LFR_METRICS
7608/**
7609 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
7610 * @pAdapter: Pointer to adapter
7611 * @pRoamInfo: Pointer to roam info
7612 *
7613 * 802.11r/LFR metrics reporting function to report preauth initiation
7614 *
7615 * Return: CDF status
7616 */
7617#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307618QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007619 tCsrRoamInfo *pRoamInfo)
7620{
7621 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7622 union iwreq_data wrqu;
7623
7624 ENTER();
7625
7626 if (NULL == pAdapter) {
7627 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307628 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007629 }
7630
7631 /* create the event */
7632 memset(&wrqu, 0, sizeof(wrqu));
7633 memset(metrics_notification, 0, sizeof(metrics_notification));
7634
7635 wrqu.data.pointer = metrics_notification;
7636 wrqu.data.length = scnprintf(metrics_notification,
7637 sizeof(metrics_notification),
7638 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
7639 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7640
7641 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7642 metrics_notification);
7643
7644 EXIT();
7645
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307646 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007647}
7648
7649/**
7650 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7651 * @pAdapter: Pointer to adapter
7652 * @pRoamInfo: Pointer to roam info
7653 * @preauth_status: Preauth status
7654 *
7655 * 802.11r/LFR metrics reporting function to report handover initiation
7656 *
7657 * Return: CDF status
7658 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307659QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007660wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
7661 tCsrRoamInfo *pRoamInfo,
7662 bool preauth_status)
7663{
7664 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7665 union iwreq_data wrqu;
7666
7667 ENTER();
7668
7669 if (NULL == pAdapter) {
7670 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307671 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007672 }
7673
7674 /* create the event */
7675 memset(&wrqu, 0, sizeof(wrqu));
7676 memset(metrics_notification, 0, sizeof(metrics_notification));
7677
7678 scnprintf(metrics_notification, sizeof(metrics_notification),
7679 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
7680 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7681
7682 if (1 == preauth_status)
7683 strlcat(metrics_notification, " true",
7684 sizeof(metrics_notification));
7685 else
7686 strlcat(metrics_notification, " false",
7687 sizeof(metrics_notification));
7688
7689 wrqu.data.pointer = metrics_notification;
7690 wrqu.data.length = strlen(metrics_notification);
7691
7692 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7693 metrics_notification);
7694
7695 EXIT();
7696
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307697 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007698}
7699
7700/**
7701 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7702 * @pAdapter: Pointer to adapter
7703 * @pRoamInfo: Pointer to roam info
7704 *
7705 * 802.11r/LFR metrics reporting function to report handover initiation
7706 *
7707 * Return: CDF status
7708 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307709QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007710 tCsrRoamInfo *pRoamInfo)
7711{
7712 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7713 union iwreq_data wrqu;
7714
7715 ENTER();
7716
7717 if (NULL == pAdapter) {
7718 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307719 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007720 }
7721
7722 /* create the event */
7723 memset(&wrqu, 0, sizeof(wrqu));
7724 memset(metrics_notification, 0, sizeof(metrics_notification));
7725
7726 wrqu.data.pointer = metrics_notification;
7727 wrqu.data.length = scnprintf(metrics_notification,
7728 sizeof(metrics_notification),
7729 "QCOM: LFR_PREAUTH_HANDOVER "
7730 MAC_ADDRESS_STR,
7731 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7732
7733 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7734 metrics_notification);
7735
7736 EXIT();
7737
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307738 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007739}
7740#endif
7741
7742/**
7743 * hdd_select_cbmode() - select channel bonding mode
7744 * @pAdapter: Pointer to adapter
7745 * @operatingChannel: Operating channel
7746 *
7747 * Return: none
7748 */
7749void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel)
7750{
7751 uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
7752 eHddDot11Mode hddDot11Mode = iniDot11Mode;
7753 chan_params_t ch_params;
7754 ch_params.ch_width =
7755 (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth;
7756
7757 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode);
7758 switch (iniDot11Mode) {
7759 case eHDD_DOT11_MODE_AUTO:
7760 case eHDD_DOT11_MODE_11ac:
7761 case eHDD_DOT11_MODE_11ac_ONLY:
7762#ifdef WLAN_FEATURE_11AC
7763 if (sme_is_feature_supported_by_fw(DOT11AC))
7764 hddDot11Mode = eHDD_DOT11_MODE_11ac;
7765 else
7766 hddDot11Mode = eHDD_DOT11_MODE_11n;
7767#else
7768 hddDot11Mode = eHDD_DOT11_MODE_11n;
7769#endif
7770 break;
7771 case eHDD_DOT11_MODE_11n:
7772 case eHDD_DOT11_MODE_11n_ONLY:
7773 hddDot11Mode = eHDD_DOT11_MODE_11n;
7774 break;
7775 default:
7776 hddDot11Mode = iniDot11Mode;
7777 break;
7778 }
7779 /* This call decides required channel bonding mode */
7780 sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal),
7781 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
7782 operationChannel, 0,
7783 &ch_params);
7784}
7785
7786
7787/*
7788 * FUNCTION: wlan_hdd_cfg80211_connect_start
7789 * wlan_hdd_cfg80211_connect_start() - start connection
7790 * @pAdapter: Pointer to adapter
7791 * @ssid: Pointer ot ssid
7792 * @ssid_len: Length of ssid
7793 * @bssid: Pointer to bssid
7794 * @operatingChannel: Operating channel
7795 *
7796 * This function is used to start the association process
7797 *
7798 * Return: 0 for success, non-zero for failure
7799 */
7800int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
7801 const u8 *ssid, size_t ssid_len,
7802 const u8 *bssid_hint, const u8 *bssid,
7803 u8 operatingChannel)
7804{
7805 int status = 0;
7806 hdd_wext_state_t *pWextState;
7807 hdd_context_t *pHddCtx;
7808 uint32_t roamId;
7809 tCsrRoamProfile *pRoamProfile;
7810 eCsrAuthType RSNAuthType;
7811 tSmeConfigParams *sme_config;
7812
7813 ENTER();
7814
7815 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7816 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7817
7818 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307819 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007820 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007821
7822 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
7823 hddLog(LOGE, FL("wrong SSID len"));
7824 return -EINVAL;
7825 }
7826
7827 pRoamProfile = &pWextState->roamProfile;
7828
7829 if (pRoamProfile) {
7830 hdd_station_ctx_t *pHddStaCtx;
7831 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7832
7833 if (HDD_WMM_USER_MODE_NO_QOS ==
7834 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
7835 /*QoS not enabled in cfg file */
7836 pRoamProfile->uapsd_mask = 0;
7837 } else {
7838 /*QoS enabled, update uapsd mask from cfg file */
7839 pRoamProfile->uapsd_mask =
7840 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
7841 }
7842
7843 pRoamProfile->SSIDs.numOfSSIDs = 1;
7844 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
7845 cdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
7846 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
7847 cdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
7848 ssid, ssid_len);
7849
7850 if (bssid) {
7851 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
7852 cdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307853 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007854 /* Save BSSID in seperate variable as well, as RoamProfile
7855 BSSID is getting zeroed out in the association process. And in
7856 case of join failure we should send valid BSSID to supplicant
7857 */
7858 cdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307859 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007860 } else if (bssid_hint) {
7861 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
7862 cdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307863 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007864 /* Save BSSID in separate variable as well, as
7865 RoamProfile BSSID is getting zeroed out in the
7866 association process. And in case of join failure
7867 we should send valid BSSID to supplicant
7868 */
7869 cdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307870 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007871 hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR),
7872 MAC_ADDR_ARRAY(bssid_hint));
7873 } else {
7874 cdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307875 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007876 }
7877
7878 hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"),
7879 pRoamProfile->SSIDs.SSIDList->SSID.length,
7880 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
7881 operatingChannel);
7882
7883 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
7884 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
7885 /*set gen ie */
7886 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
7887 /*set auth */
7888 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
7889 }
7890#ifdef FEATURE_WLAN_WAPI
7891 if (pAdapter->wapi_info.nWapiMode) {
7892 hddLog(LOG1,
7893 FL("Setting WAPI AUTH Type and Encryption Mode values"));
7894 switch (pAdapter->wapi_info.wapiAuthMode) {
7895 case WAPI_AUTH_MODE_PSK:
7896 {
7897 hddLog(LOG1,
7898 FL("WAPI AUTH TYPE: PSK: %d"),
7899 pAdapter->wapi_info.wapiAuthMode);
7900 pRoamProfile->AuthType.authType[0] =
7901 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
7902 break;
7903 }
7904 case WAPI_AUTH_MODE_CERT:
7905 {
7906 hddLog(LOG1,
7907 FL("WAPI AUTH TYPE: CERT: %d"),
7908 pAdapter->wapi_info.wapiAuthMode);
7909 pRoamProfile->AuthType.authType[0] =
7910 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
7911 break;
7912 }
7913 } /* End of switch */
7914 if (pAdapter->wapi_info.wapiAuthMode ==
7915 WAPI_AUTH_MODE_PSK
7916 || pAdapter->wapi_info.wapiAuthMode ==
7917 WAPI_AUTH_MODE_CERT) {
7918 hddLog(LOG1,
7919 FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI"));
7920 pRoamProfile->AuthType.numEntries = 1;
7921 pRoamProfile->EncryptionType.numEntries = 1;
7922 pRoamProfile->EncryptionType.encryptionType[0] =
7923 eCSR_ENCRYPT_TYPE_WPI;
7924 pRoamProfile->mcEncryptionType.numEntries = 1;
7925 pRoamProfile->mcEncryptionType.
7926 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
7927 }
7928 }
7929#endif /* FEATURE_WLAN_WAPI */
7930#ifdef WLAN_FEATURE_GTK_OFFLOAD
7931 /* Initializing gtkOffloadReqParams */
7932 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7933 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
7934 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
7935 sizeof(tSirGtkOffloadParams));
7936 pHddStaCtx->gtkOffloadReqParams.ulFlags =
7937 GTK_OFFLOAD_DISABLE;
7938 }
7939#endif
7940 pRoamProfile->csrPersona = pAdapter->device_mode;
7941
7942 if (operatingChannel) {
7943 pRoamProfile->ChannelInfo.ChannelList =
7944 &operatingChannel;
7945 pRoamProfile->ChannelInfo.numOfChannels = 1;
7946 } else {
7947 pRoamProfile->ChannelInfo.ChannelList = NULL;
7948 pRoamProfile->ChannelInfo.numOfChannels = 0;
7949 }
7950 if ((WLAN_HDD_IBSS == pAdapter->device_mode)
7951 && operatingChannel) {
7952 /*
7953 * Need to post the IBSS power save parameters
7954 * to WMA. WMA will configure this parameters
7955 * to firmware if power save is enabled by the
7956 * firmware.
7957 */
7958 status = hdd_set_ibss_power_save_params(pAdapter);
7959
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307960 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007961 hddLog(LOGE,
7962 FL("Set IBSS Power Save Params Failed"));
7963 return -EINVAL;
7964 }
7965 hdd_select_cbmode(pAdapter, operatingChannel);
7966 }
7967
7968 if (pHddCtx->config->policy_manager_enabled &&
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08007969 (true == cds_is_connection_in_progress())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007970 hdd_err("Connection refused: conn in progress");
7971 return -EINVAL;
7972 }
7973
7974 /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect()
7975 * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state
7976 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
7977 * by either hdd_association_completion_handler() or hdd_dis_connect_handler() in sme_RoamCallback()
7978 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
7979 */
7980 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7981 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) {
7982 hddLog(LOG1,
7983 FL("Set HDD connState to eConnectionState_Connecting"));
7984 hdd_conn_set_connection_state(pAdapter,
7985 eConnectionState_Connecting);
7986 }
7987
7988 /* After 8-way handshake supplicant should give the scan command
7989 * in that it update the additional IEs, But because of scan
7990 * enhancements, the supplicant is not issuing the scan command now.
7991 * So the unicast frames which are sent from the host are not having
7992 * the additional IEs. If it is P2P CLIENT and there is no additional
7993 * IE present in roamProfile, then use the addtional IE form scan_info
7994 */
7995
7996 if ((pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
7997 (!pRoamProfile->pAddIEScan)) {
7998 pRoamProfile->pAddIEScan =
7999 &pAdapter->scan_info.scanAddIE.addIEdata[0];
8000 pRoamProfile->nAddIEScanLength =
8001 pAdapter->scan_info.scanAddIE.length;
8002 }
8003 /*
8004 * When policy manager is enabled from ini file, we shouldn't
8005 * check for other concurrency rules.
8006 */
8007 if (!pHddCtx->config->policy_manager_enabled) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008008 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008009 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008010 pAdapter, pRoamProfile, &roamId))
8011 return 0;
8012 }
8013
8014 sme_config = cdf_mem_malloc(sizeof(*sme_config));
8015 if (!sme_config) {
8016 hdd_err("unable to allocate sme_config");
8017 return -ENOMEM;
8018 }
8019 cdf_mem_zero(sme_config, sizeof(*sme_config));
8020 sme_get_config_param(pHddCtx->hHal, sme_config);
8021 /* These values are not sessionized. So, any change in these SME
8022 * configs on an older or parallel interface will affect the
8023 * cb mode. So, restoring the default INI params before starting
8024 * interfaces such as sta, cli etc.,
8025 */
8026 sme_config->csrConfig.channelBondingMode5GHz =
8027 pHddCtx->config->nChannelBondingMode5GHz;
8028 sme_config->csrConfig.channelBondingMode24GHz =
8029 pHddCtx->config->nChannelBondingMode24GHz;
8030 sme_update_config(pHddCtx->hHal, sme_config);
8031 cdf_mem_free(sme_config);
8032
8033 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8034 pAdapter->sessionId, pRoamProfile,
8035 &roamId);
8036
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308037 if ((QDF_STATUS_SUCCESS != status) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008038 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
8039 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
8040 hddLog(LOGE,
8041 FL("sme_roam_connect (session %d) failed with "
8042 "status %d. -> NotConnected"),
8043 pAdapter->sessionId, status);
8044 /* change back to NotAssociated */
8045 hdd_conn_set_connection_state(pAdapter,
8046 eConnectionState_NotConnected);
8047 }
8048
8049 pRoamProfile->ChannelInfo.ChannelList = NULL;
8050 pRoamProfile->ChannelInfo.numOfChannels = 0;
8051
8052 } else {
8053 hddLog(LOGE, FL("No valid Roam profile"));
8054 return -EINVAL;
8055 }
8056 EXIT();
8057 return status;
8058}
8059
8060/**
8061 * wlan_hdd_cfg80211_set_auth_type() - set auth type
8062 * @pAdapter: Pointer to adapter
8063 * @auth_type: Auth type
8064 *
8065 * This function is used to set the authentication type (OPEN/SHARED).
8066 *
8067 * Return: 0 for success, non-zero for failure
8068 */
8069static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
8070 enum nl80211_auth_type auth_type)
8071{
8072 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8073 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8074
8075 ENTER();
8076
8077 /*set authentication type */
8078 switch (auth_type) {
8079 case NL80211_AUTHTYPE_AUTOMATIC:
8080 hddLog(LOG1,
8081 FL("set authentication type to AUTOSWITCH"));
8082 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
8083 break;
8084
8085 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008086 case NL80211_AUTHTYPE_FT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008087 hddLog(LOG1,
8088 FL("set authentication type to OPEN"));
8089 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8090 break;
8091
8092 case NL80211_AUTHTYPE_SHARED_KEY:
8093 hddLog(LOG1,
8094 FL("set authentication type to SHARED"));
8095 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
8096 break;
8097#ifdef FEATURE_WLAN_ESE
8098 case NL80211_AUTHTYPE_NETWORK_EAP:
8099 hddLog(LOG1,
8100 FL("set authentication type to CCKM WPA"));
8101 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
8102 break;
8103#endif
8104
8105 default:
8106 hddLog(LOGE,
8107 FL("Unsupported authentication type %d"), auth_type);
8108 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
8109 return -EINVAL;
8110 }
8111
8112 pWextState->roamProfile.AuthType.authType[0] =
8113 pHddStaCtx->conn_info.authType;
8114 return 0;
8115}
8116
8117/**
8118 * wlan_hdd_set_akm_suite() - set key management type
8119 * @pAdapter: Pointer to adapter
8120 * @key_mgmt: Key management type
8121 *
8122 * This function is used to set the key mgmt type(PSK/8021x).
8123 *
8124 * Return: 0 for success, non-zero for failure
8125 */
8126static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
8127{
8128 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8129
8130 ENTER();
8131
8132#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
8133#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
8134 /*set key mgmt type */
8135 switch (key_mgmt) {
8136 case WLAN_AKM_SUITE_PSK:
8137 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008138 case WLAN_AKM_SUITE_FT_PSK:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008139 hddLog(LOG1, FL("setting key mgmt type to PSK"));
8140 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
8141 break;
8142
8143 case WLAN_AKM_SUITE_8021X_SHA256:
8144 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008145 case WLAN_AKM_SUITE_FT_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008146 hddLog(LOG1,
8147 FL("setting key mgmt type to 8021x"));
8148 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8149 break;
8150#ifdef FEATURE_WLAN_ESE
8151#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
8152#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
8153 case WLAN_AKM_SUITE_CCKM:
8154 hddLog(LOG1,
8155 FL("setting key mgmt type to CCKM"));
8156 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
8157 break;
8158#endif
8159#ifndef WLAN_AKM_SUITE_OSEN
8160#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
8161#endif
8162 case WLAN_AKM_SUITE_OSEN:
8163 hddLog(LOG1,
8164 FL("setting key mgmt type to OSEN"));
8165 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8166 break;
8167
8168 default:
8169 hddLog(LOGE,
8170 FL("Unsupported key mgmt type %d"), key_mgmt);
8171 return -EINVAL;
8172
8173 }
8174 return 0;
8175}
8176
8177/**
8178 * wlan_hdd_cfg80211_set_cipher() - set encryption type
8179 * @pAdapter: Pointer to adapter
8180 * @cipher: Cipher type
8181 * @ucast: Unicast flag
8182 *
8183 * This function is used to set the encryption type
8184 * (NONE/WEP40/WEP104/TKIP/CCMP).
8185 *
8186 * Return: 0 for success, non-zero for failure
8187 */
8188static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
8189 u32 cipher, bool ucast)
8190{
8191 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8192 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8193 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8194
8195 ENTER();
8196
8197 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008198 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008199 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8200 } else {
8201
8202 /*set encryption method */
8203 switch (cipher) {
8204 case IW_AUTH_CIPHER_NONE:
8205 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8206 break;
8207
8208 case WLAN_CIPHER_SUITE_WEP40:
8209 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
8210 break;
8211
8212 case WLAN_CIPHER_SUITE_WEP104:
8213 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
8214 break;
8215
8216 case WLAN_CIPHER_SUITE_TKIP:
8217 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
8218 break;
8219
8220 case WLAN_CIPHER_SUITE_CCMP:
8221 encryptionType = eCSR_ENCRYPT_TYPE_AES;
8222 break;
8223#ifdef FEATURE_WLAN_WAPI
8224 case WLAN_CIPHER_SUITE_SMS4:
8225 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
8226 break;
8227#endif
8228
8229#ifdef FEATURE_WLAN_ESE
8230 case WLAN_CIPHER_SUITE_KRK:
8231 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
8232 break;
8233#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8234 case WLAN_CIPHER_SUITE_BTK:
8235 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
8236 break;
8237#endif
8238#endif
8239 default:
8240 hddLog(LOGE,
8241 FL("Unsupported cipher type %d"), cipher);
8242 return -EOPNOTSUPP;
8243 }
8244 }
8245
8246 if (ucast) {
8247 hddLog(LOG1,
8248 FL("setting unicast cipher type to %d"), encryptionType);
8249 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
8250 pWextState->roamProfile.EncryptionType.numEntries = 1;
8251 pWextState->roamProfile.EncryptionType.encryptionType[0] =
8252 encryptionType;
8253 } else {
8254 hddLog(LOG1,
8255 FL("setting mcast cipher type to %d"), encryptionType);
8256 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
8257 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
8258 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
8259 encryptionType;
8260 }
8261
8262 return 0;
8263}
8264
8265/**
8266 * wlan_hdd_cfg80211_set_ie() - set IEs
8267 * @pAdapter: Pointer to adapter
8268 * @ie: Pointer ot ie
8269 * @ie: IE length
8270 *
8271 * Return: 0 for success, non-zero for failure
8272 */
8273int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
8274 size_t ie_len)
8275{
8276 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8277 const uint8_t *genie = ie;
8278 uint16_t remLen = ie_len;
8279#ifdef FEATURE_WLAN_WAPI
8280 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
8281 u16 *tmp;
8282 uint16_t akmsuiteCount;
8283 int *akmlist;
8284#endif
8285 ENTER();
8286
8287 /* clear previous assocAddIE */
8288 pWextState->assocAddIE.length = 0;
8289 pWextState->roamProfile.bWPSAssociation = false;
8290 pWextState->roamProfile.bOSENAssociation = false;
8291
8292 while (remLen >= 2) {
8293 uint16_t eLen = 0;
8294 uint8_t elementId;
8295 elementId = *genie++;
8296 eLen = *genie++;
8297 remLen -= 2;
8298
8299 hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), elementId, eLen);
8300
8301 switch (elementId) {
8302 case DOT11F_EID_WPA:
8303 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
8304 hddLog(LOGE, FL("Invalid WPA IE"));
8305 return -EINVAL;
8306 } else if (0 ==
8307 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
8308 uint16_t curAddIELen =
8309 pWextState->assocAddIE.length;
8310 hddLog(LOG1,
8311 FL("Set WPS IE(len %d)"), eLen + 2);
8312
8313 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8314 (pWextState->assocAddIE.length + eLen)) {
8315 hddLog(LOGE,
8316 FL("Cannot accommodate assocAddIE. Need bigger buffer space"));
8317 CDF_ASSERT(0);
8318 return -ENOMEM;
8319 }
8320 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8321 memcpy(pWextState->assocAddIE.addIEdata +
8322 curAddIELen, genie - 2, eLen + 2);
8323 pWextState->assocAddIE.length += eLen + 2;
8324
8325 pWextState->roamProfile.bWPSAssociation = true;
8326 pWextState->roamProfile.pAddIEAssoc =
8327 pWextState->assocAddIE.addIEdata;
8328 pWextState->roamProfile.nAddIEAssocLength =
8329 pWextState->assocAddIE.length;
8330 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
8331 hddLog(LOG1,
8332 FL("Set WPA IE (len %d)"), eLen + 2);
8333 memset(pWextState->WPARSNIE, 0,
8334 MAX_WPA_RSN_IE_LEN);
8335 memcpy(pWextState->WPARSNIE, genie - 2,
8336 (eLen + 2));
8337 pWextState->roamProfile.pWPAReqIE =
8338 pWextState->WPARSNIE;
8339 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
8340 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
8341 P2P_OUI_TYPE_SIZE))) {
8342 uint16_t curAddIELen =
8343 pWextState->assocAddIE.length;
8344 hddLog(LOG1,
8345 FL("Set P2P IE(len %d)"), eLen + 2);
8346
8347 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8348 (pWextState->assocAddIE.length + eLen)) {
8349 hddLog(LOGE,
8350 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
8351 CDF_ASSERT(0);
8352 return -ENOMEM;
8353 }
8354 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8355 memcpy(pWextState->assocAddIE.addIEdata +
8356 curAddIELen, genie - 2, eLen + 2);
8357 pWextState->assocAddIE.length += eLen + 2;
8358
8359 pWextState->roamProfile.pAddIEAssoc =
8360 pWextState->assocAddIE.addIEdata;
8361 pWextState->roamProfile.nAddIEAssocLength =
8362 pWextState->assocAddIE.length;
8363 }
8364#ifdef WLAN_FEATURE_WFD
8365 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
8366 WFD_OUI_TYPE_SIZE)) &&
8367 /* Consider WFD IE, only for P2P Client */
8368 (WLAN_HDD_P2P_CLIENT ==
8369 pAdapter->device_mode)) {
8370 uint16_t curAddIELen =
8371 pWextState->assocAddIE.length;
8372 hddLog(LOG1,
8373 FL("Set WFD IE(len %d)"), eLen + 2);
8374
8375 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8376 (pWextState->assocAddIE.length + eLen)) {
8377 hddLog(LOGE,
8378 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
8379 CDF_ASSERT(0);
8380 return -ENOMEM;
8381 }
8382 /* WFD IE is saved to Additional IE ; it should
8383 * be accumulated to handle WPS IE + P2P IE +
8384 * WFD IE */
8385 memcpy(pWextState->assocAddIE.addIEdata +
8386 curAddIELen, genie - 2, eLen + 2);
8387 pWextState->assocAddIE.length += eLen + 2;
8388
8389 pWextState->roamProfile.pAddIEAssoc =
8390 pWextState->assocAddIE.addIEdata;
8391 pWextState->roamProfile.nAddIEAssocLength =
8392 pWextState->assocAddIE.length;
8393 }
8394#endif
8395 /* Appending HS 2.0 Indication Element in Assiciation Request */
8396 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
8397 HS20_OUI_TYPE_SIZE))) {
8398 uint16_t curAddIELen =
8399 pWextState->assocAddIE.length;
8400 hddLog(LOG1,
8401 FL("Set HS20 IE(len %d)"), eLen + 2);
8402
8403 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8404 (pWextState->assocAddIE.length + eLen)) {
8405 hddLog(LOGE,
8406 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
8407 CDF_ASSERT(0);
8408 return -ENOMEM;
8409 }
8410 memcpy(pWextState->assocAddIE.addIEdata +
8411 curAddIELen, genie - 2, eLen + 2);
8412 pWextState->assocAddIE.length += eLen + 2;
8413
8414 pWextState->roamProfile.pAddIEAssoc =
8415 pWextState->assocAddIE.addIEdata;
8416 pWextState->roamProfile.nAddIEAssocLength =
8417 pWextState->assocAddIE.length;
8418 }
8419 /* Appending OSEN Information Element in Assiciation Request */
8420 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
8421 OSEN_OUI_TYPE_SIZE))) {
8422 uint16_t curAddIELen =
8423 pWextState->assocAddIE.length;
8424 hddLog(LOG1,
8425 FL("Set OSEN IE(len %d)"), eLen + 2);
8426
8427 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8428 (pWextState->assocAddIE.length + eLen)) {
8429 hddLog(LOGE,
8430 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
8431 CDF_ASSERT(0);
8432 return -ENOMEM;
8433 }
8434 memcpy(pWextState->assocAddIE.addIEdata +
8435 curAddIELen, genie - 2, eLen + 2);
8436 pWextState->assocAddIE.length += eLen + 2;
8437
8438 pWextState->roamProfile.bOSENAssociation = true;
8439 pWextState->roamProfile.pAddIEAssoc =
8440 pWextState->assocAddIE.addIEdata;
8441 pWextState->roamProfile.nAddIEAssocLength =
8442 pWextState->assocAddIE.length;
8443 } else {
8444 uint16_t add_ie_len =
8445 pWextState->assocAddIE.length;
8446
8447 hdd_info("Set OSEN IE(len %d)", eLen + 2);
8448
8449 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8450 (pWextState->assocAddIE.length + eLen)) {
8451 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
8452 CDF_ASSERT(0);
8453 return -ENOMEM;
8454 }
8455
8456 memcpy(pWextState->assocAddIE.addIEdata +
8457 add_ie_len, genie - 2, eLen + 2);
8458 pWextState->assocAddIE.length += eLen + 2;
8459
8460 pWextState->roamProfile.pAddIEAssoc =
8461 pWextState->assocAddIE.addIEdata;
8462 pWextState->roamProfile.nAddIEAssocLength =
8463 pWextState->assocAddIE.length;
8464 }
8465 break;
8466 case DOT11F_EID_RSN:
8467 hddLog(LOG1, FL("Set RSN IE(len %d)"), eLen + 2);
8468 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
8469 memcpy(pWextState->WPARSNIE, genie - 2,
8470 (eLen + 2));
8471 pWextState->roamProfile.pRSNReqIE =
8472 pWextState->WPARSNIE;
8473 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
8474 break;
8475 /*
8476 * Appending Extended Capabilities with Interworking bit set
8477 * in Assoc Req.
8478 *
8479 * In assoc req this EXT Cap will only be taken into account if
8480 * interworkingService bit is set to 1. Currently
8481 * driver is only interested in interworkingService capability
8482 * from supplicant. If in future any other EXT Cap info is
8483 * required from supplicat, it needs to be handled while
8484 * sending Assoc Req in LIM.
8485 */
8486 case DOT11F_EID_EXTCAP:
8487 {
8488 uint16_t curAddIELen =
8489 pWextState->assocAddIE.length;
8490 hddLog(LOG1,
8491 FL("Set Extended CAPS IE(len %d)"), eLen + 2);
8492
8493 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8494 (pWextState->assocAddIE.length + eLen)) {
8495 hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space"));
8496 CDF_ASSERT(0);
8497 return -ENOMEM;
8498 }
8499 memcpy(pWextState->assocAddIE.addIEdata +
8500 curAddIELen, genie - 2, eLen + 2);
8501 pWextState->assocAddIE.length += eLen + 2;
8502
8503 pWextState->roamProfile.pAddIEAssoc =
8504 pWextState->assocAddIE.addIEdata;
8505 pWextState->roamProfile.nAddIEAssocLength =
8506 pWextState->assocAddIE.length;
8507 break;
8508 }
8509#ifdef FEATURE_WLAN_WAPI
8510 case WLAN_EID_WAPI:
8511 /* Setting WAPI Mode to ON=1 */
8512 pAdapter->wapi_info.nWapiMode = 1;
8513 hddLog(LOG1,
8514 FL("WAPI MODE IS %u"), pAdapter->wapi_info.nWapiMode);
8515 tmp = (u16 *) ie;
8516 tmp = tmp + 2; /* Skip element Id and Len, Version */
8517 akmsuiteCount = WPA_GET_LE16(tmp);
8518 tmp = tmp + 1;
8519 akmlist = (int *)(tmp);
8520 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
8521 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
8522 } else {
8523 hddLog(LOGE,
8524 FL("Invalid akmSuite count"));
8525 CDF_ASSERT(0);
8526 return -EINVAL;
8527 }
8528
8529 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
8530 hddLog(LOG1,
8531 FL("WAPI AUTH MODE SET TO PSK"));
8532 pAdapter->wapi_info.wapiAuthMode =
8533 WAPI_AUTH_MODE_PSK;
8534 }
8535 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
8536 hddLog(LOG1,
8537 FL("WAPI AUTH MODE SET TO CERTIFICATE"));
8538 pAdapter->wapi_info.wapiAuthMode =
8539 WAPI_AUTH_MODE_CERT;
8540 }
8541 break;
8542#endif
8543 default:
8544 hddLog(LOGE,
8545 FL("Set UNKNOWN IE %X"), elementId);
8546 /* when Unknown IE is received we should break and continue
8547 * to the next IE in the buffer instead we were returning
8548 * so changing this to break */
8549 break;
8550 }
8551 genie += eLen;
8552 remLen -= eLen;
8553 }
8554 EXIT();
8555 return 0;
8556}
8557
8558/**
8559 * hdd_is_wpaie_present() - check for WPA ie
8560 * @ie: Pointer to ie
8561 * @ie_len: Ie length
8562 *
8563 * Parse the received IE to find the WPA IE
8564 *
8565 * Return: true if wpa ie is found else false
8566 */
8567static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
8568{
8569 uint8_t eLen = 0;
8570 uint16_t remLen = ie_len;
8571 uint8_t elementId = 0;
8572
8573 while (remLen >= 2) {
8574 elementId = *ie++;
8575 eLen = *ie++;
8576 remLen -= 2;
8577 if (eLen > remLen) {
8578 hddLog(CDF_TRACE_LEVEL_ERROR,
8579 "%s: IE length is wrong %d", __func__, eLen);
8580 return false;
8581 }
8582 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
8583 /* OUI - 0x00 0X50 0XF2
8584 * WPA Information Element - 0x01
8585 * WPA version - 0x01
8586 */
8587 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
8588 return true;
8589 }
8590 ie += eLen;
8591 remLen -= eLen;
8592 }
8593 return false;
8594}
8595
8596/**
8597 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
8598 * @pAdapter: Pointer to adapter
8599 * @req: Pointer to security parameters
8600 *
8601 * Return: 0 for success, non-zero for failure
8602 */
8603int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
8604 struct cfg80211_connect_params *req)
8605{
8606 int status = 0;
8607 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8608 ENTER();
8609
8610 /*set wpa version */
8611 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
8612
8613 if (req->crypto.wpa_versions) {
8614 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
8615 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
8616 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
8617 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
8618 }
8619 }
8620
8621 hddLog(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion);
8622
8623 /*set authentication type */
8624 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
8625
8626 if (0 > status) {
8627 hddLog(LOGE, FL("failed to set authentication type "));
8628 return status;
8629 }
8630
8631 /*set key mgmt type */
8632 if (req->crypto.n_akm_suites) {
8633 status =
8634 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
8635 if (0 > status) {
8636 hddLog(LOGE, FL("failed to set akm suite"));
8637 return status;
8638 }
8639 }
8640
8641 /*set pairwise cipher type */
8642 if (req->crypto.n_ciphers_pairwise) {
8643 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
8644 req->crypto.
8645 ciphers_pairwise[0],
8646 true);
8647 if (0 > status) {
8648 hddLog(LOGE, FL("failed to set unicast cipher type"));
8649 return status;
8650 }
8651 } else {
8652 /*Reset previous cipher suite to none */
8653 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
8654 if (0 > status) {
8655 hddLog(LOGE, FL("failed to set unicast cipher type"));
8656 return status;
8657 }
8658 }
8659
8660 /*set group cipher type */
8661 status =
8662 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
8663 false);
8664
8665 if (0 > status) {
8666 hddLog(LOGE, FL("failed to set mcast cipher type"));
8667 return status;
8668 }
8669#ifdef WLAN_FEATURE_11W
8670 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
8671#endif
8672
8673 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
8674 if (req->ie_len) {
8675 status =
8676 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
8677 if (0 > status) {
8678 hddLog(LOGE, FL("failed to parse the WPA/RSN IE"));
8679 return status;
8680 }
8681 }
8682
8683 /*incase of WEP set default key information */
8684 if (req->key && req->key_len) {
8685 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
8686 || (WLAN_CIPHER_SUITE_WEP104 ==
8687 req->crypto.ciphers_pairwise[0])
8688 ) {
8689 if (IW_AUTH_KEY_MGMT_802_1X
8690 ==
8691 (pWextState->
8692 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
8693 hddLog(LOGE,
8694 FL("Dynamic WEP not supported"));
8695 return -EOPNOTSUPP;
8696 } else {
8697 u8 key_len = req->key_len;
8698 u8 key_idx = req->key_idx;
8699
8700 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
8701 key_len)
8702 && (CSR_MAX_NUM_KEY > key_idx)
8703 ) {
8704 hddLog(LOG1,
8705 FL("setting default wep key, key_idx = %hu key_len %hu"),
8706 key_idx, key_len);
8707 cdf_mem_copy(&pWextState->roamProfile.
8708 Keys.
8709 KeyMaterial[key_idx][0],
8710 req->key, key_len);
8711 pWextState->roamProfile.Keys.
8712 KeyLength[key_idx] = (u8) key_len;
8713 pWextState->roamProfile.Keys.
8714 defaultIndex = (u8) key_idx;
8715 }
8716 }
8717 }
8718 }
8719
8720 return status;
8721}
8722
8723/**
8724 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
8725 * @pAdapter: Pointer to adapter
8726 *
8727 * This function is used to disconnect from previous connection
8728 *
8729 * Return: 0 for success, non-zero for failure
8730 */
8731static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
8732{
8733 unsigned long rc;
8734 hdd_station_ctx_t *pHddStaCtx;
8735 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308736 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008737
8738 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8739
8740 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
8741
8742 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +05308743 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
8744 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
8745 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008746 hdd_conn_set_connection_state(pAdapter,
8747 eConnectionState_Disconnecting);
8748 /* Issue disconnect to CSR */
8749 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308750
8751 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8752 pAdapter->sessionId,
8753 eCSR_DISCONNECT_REASON_UNSPECIFIED);
8754 /*
8755 * Wait here instead of returning directly, this will block the
8756 * next connect command and allow processing of the scan for
8757 * ssid and the previous connect command in CSR. Else we might
8758 * hit some race conditions leading to SME and HDD out of sync.
8759 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308760 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308761 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
8762 } else if (0 != status) {
8763 hdd_err("csrRoamDisconnect failure, returned %d",
8764 (int)status);
8765 pHddStaCtx->staDebugState = status;
8766 result = -EINVAL;
8767 goto disconnected;
8768 }
8769
8770 rc = wait_for_completion_timeout(
8771 &pAdapter->disconnect_comp_var,
8772 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308773 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308774 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
8775 pAdapter->sessionId, pHddStaCtx->staDebugState);
8776 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008777 }
8778 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308779 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008780 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308781 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008782 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308783 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008784 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308785 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008786 }
8787 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308788disconnected:
8789 hdd_info("Set HDD connState to eConnectionState_NotConnected");
8790 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
8791 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008792}
8793
8794/**
8795 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
8796 * @wiphy: Pointer to wiphy
8797 * @dev: Pointer to network device
8798 * @req: Pointer to cfg80211 connect request
8799 *
8800 * This function is used to start the association process
8801 *
8802 * Return: 0 for success, non-zero for failure
8803 */
8804static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8805 struct net_device *ndev,
8806 struct cfg80211_connect_params *req)
8807{
8808 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05308809 u16 channel;
8810#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
8811 const u8 *bssid_hint = req->bssid_hint;
8812#else
8813 const u8 *bssid_hint = NULL;
8814#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008815 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8816 hdd_context_t *pHddCtx;
8817
8818 ENTER();
8819
Anurag Chouhan6d760662016-02-20 16:05:43 +05308820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008821 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8822 return -EINVAL;
8823 }
8824
Anurag Chouhan6d760662016-02-20 16:05:43 +05308825 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008826 TRACE_CODE_HDD_CFG80211_CONNECT,
8827 pAdapter->sessionId, pAdapter->device_mode));
8828 hddLog(LOG1, FL("Device_mode %s(%d)"),
8829 hdd_device_mode_to_string(pAdapter->device_mode),
8830 pAdapter->device_mode);
8831
8832 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION &&
8833 pAdapter->device_mode != WLAN_HDD_P2P_CLIENT) {
8834 hddLog(LOGE, FL("Device_mode %s(%d) is not supported"),
8835 hdd_device_mode_to_string(pAdapter->device_mode),
8836 pAdapter->device_mode);
8837 return -EINVAL;
8838 }
8839
8840 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8841 if (!pHddCtx) {
8842 hddLog(LOGE, FL("HDD context is null"));
8843 return -EINVAL;
8844 }
8845
8846 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308847 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008848 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008849 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008850 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008851 cds_convert_device_mode_to_hdd_type(
8852 pAdapter->device_mode),
8853 req->channel->hw_value, HW_MODE_20_MHZ)) {
8854 hdd_err("This concurrency combination is not allowed");
8855 return -ECONNREFUSED;
8856 }
8857 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008858 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008859 cds_convert_device_mode_to_hdd_type(
8860 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
8861 hdd_err("This concurrency combination is not allowed");
8862 return -ECONNREFUSED;
8863 }
8864 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008865 wlan_hdd_disable_roaming(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008866
8867 /*Try disconnecting if already in connected state */
8868 status = wlan_hdd_try_disconnect(pAdapter);
8869 if (0 > status) {
8870 hddLog(LOGE,
8871 FL("Failed to disconnect the existing connection"));
8872 return -EALREADY;
8873 }
8874
8875 /*initialise security parameters */
8876 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
8877
8878 if (0 > status) {
8879 hddLog(LOGE,
8880 FL("failed to set security params"));
8881 return status;
8882 }
8883
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05308884 if (req->channel)
8885 channel = req->channel->hw_value;
8886 else
8887 channel = 0;
8888 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
8889 req->ssid_len, req->bssid,
8890 bssid_hint, channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008891 if (0 > status) {
8892 hddLog(LOGE, FL("connect failed"));
8893 return status;
8894 }
8895 EXIT();
8896 return status;
8897}
8898
8899/**
8900 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
8901 * @wiphy: Pointer to wiphy
8902 * @dev: Pointer to network device
8903 * @req: Pointer to cfg80211 connect request
8904 *
8905 * Return: 0 for success, non-zero for failure
8906 */
8907static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8908 struct net_device *ndev,
8909 struct cfg80211_connect_params *req)
8910{
8911 int ret;
8912 cds_ssr_protect(__func__);
8913 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
8914 cds_ssr_unprotect(__func__);
8915
8916 return ret;
8917}
8918
8919/**
8920 * wlan_hdd_disconnect() - hdd disconnect api
8921 * @pAdapter: Pointer to adapter
8922 * @reason: Disconnect reason code
8923 *
8924 * This function is used to issue a disconnect request to SME
8925 *
8926 * Return: 0 for success, non-zero for failure
8927 */
8928int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
8929{
8930 int status, result = 0;
8931 unsigned long rc;
8932 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8933 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8934
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308935 ENTER();
8936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008937 status = wlan_hdd_validate_context(pHddCtx);
8938
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308939 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008940 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008941
8942 /*stop tx queues */
8943 hddLog(LOG1, FL("Disabling queues"));
8944 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
8945 WLAN_CONTROL_PATH);
8946 hddLog(LOG1,
8947 FL("Set HDD connState to eConnectionState_Disconnecting"));
8948 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
8949 INIT_COMPLETION(pAdapter->disconnect_comp_var);
8950
8951 /*issue disconnect */
8952
8953 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8954 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +05308955 /*
8956 * Wait here instead of returning directly, this will block the next
8957 * connect command and allow processing of the scan for ssid and
8958 * the previous connect command in CSR. Else we might hit some
8959 * race conditions leading to SME and HDD out of sync.
8960 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308961 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308962 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008963 } else if (0 != status) {
8964 hddLog(LOGE,
8965 FL("csr_roam_disconnect failure, returned %d"),
8966 (int)status);
8967 pHddStaCtx->staDebugState = status;
8968 result = -EINVAL;
8969 goto disconnected;
8970 }
8971 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
8972 msecs_to_jiffies
8973 (WLAN_WAIT_TIME_DISCONNECT));
8974
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308975 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008976 hddLog(LOGE,
8977 FL("Failed to disconnect, timed out"));
8978 result = -ETIMEDOUT;
8979 }
8980disconnected:
8981 hddLog(LOG1,
8982 FL("Set HDD connState to eConnectionState_NotConnected"));
8983 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
8984#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
8985 /* Sending disconnect event to userspace for kernel version < 3.11
8986 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
8987 */
8988 hddLog(LOG1, FL("Send disconnected event to userspace"));
8989 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
8990 NULL, 0, GFP_KERNEL);
8991#endif
8992
8993 return result;
8994}
8995
8996/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008997 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
8998 * @reason: ieee80211 reason code.
8999 *
9000 * This utility function helps log string conversion of reason code.
9001 *
9002 * Return: string conversion of reason code, if match found;
9003 * "Unknown" otherwise.
9004 */
9005static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
9006{
9007 switch (reason) {
9008 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
9009 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
9010 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
9011 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
9012 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
9013 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
9014 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
9015 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
9016 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
9017 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
9018 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
9019 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
9020 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
9021 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
9022 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
9023 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
9024 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
9025 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
9026 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
9027 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
9028 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
9029 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
9030 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
9031 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
9032 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
9033 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
9034 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
9035 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
9036 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
9037 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
9038 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
9039 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
9040 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
9041 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
9042 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
9043 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
9044 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
9045 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
9046 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
9047 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
9048 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
9049 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
9050 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
9051 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
9052 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
9053 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
9054 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
9055 default:
9056 return "Unknown";
9057 }
9058}
9059
9060/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009061 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9062 * @wiphy: Pointer to wiphy
9063 * @dev: Pointer to network device
9064 * @reason: Disconnect reason code
9065 *
9066 * This function is used to issue a disconnect request to SME
9067 *
9068 * Return: 0 for success, non-zero for failure
9069 */
9070static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9071 struct net_device *dev, u16 reason)
9072{
9073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9074 int status;
9075 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9076 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9077#ifdef FEATURE_WLAN_TDLS
9078 uint8_t staIdx;
9079#endif
9080
9081 ENTER();
9082
Anurag Chouhan6d760662016-02-20 16:05:43 +05309083 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009084 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9085 return -EINVAL;
9086 }
9087
Anurag Chouhan6d760662016-02-20 16:05:43 +05309088 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009089 TRACE_CODE_HDD_CFG80211_DISCONNECT,
9090 pAdapter->sessionId, reason));
9091 hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"),
9092 hdd_device_mode_to_string(pAdapter->device_mode),
9093 pAdapter->device_mode, reason);
9094
9095 status = wlan_hdd_validate_context(pHddCtx);
9096
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309097 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009098 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099
9100 /* Issue disconnect request to SME, if station is in connected state */
9101 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
9102 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
9103 eCsrRoamDisconnectReason reasonCode =
9104 eCSR_DISCONNECT_REASON_UNSPECIFIED;
9105 hdd_scaninfo_t *pScanInfo;
9106
9107 switch (reason) {
9108 case WLAN_REASON_MIC_FAILURE:
9109 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
9110 break;
9111
9112 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
9113 case WLAN_REASON_DISASSOC_AP_BUSY:
9114 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
9115 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
9116 break;
9117
9118 case WLAN_REASON_PREV_AUTH_NOT_VALID:
9119 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
9120 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
9121 break;
9122
9123 case WLAN_REASON_DEAUTH_LEAVING:
9124 reasonCode =
9125 pHddCtx->config->
9126 gEnableDeauthToDisassocMap ?
9127 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
9128 eCSR_DISCONNECT_REASON_DEAUTH;
9129 break;
9130 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
9131 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
9132 break;
9133 default:
9134 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
9135 break;
9136 }
9137 hddLog(LOG1,
9138 FL("convert to internal reason %d to reasonCode %d"),
9139 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009140 pScanInfo = &pAdapter->scan_info;
9141 if (pScanInfo->mScanPending) {
9142 hddLog(LOG1,
9143 FL("Disconnect is in progress, Aborting Scan"));
9144 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
9145 eCSR_SCAN_ABORT_DEFAULT);
9146 }
9147#ifdef FEATURE_WLAN_TDLS
9148 /* First clean up the tdls peers if any */
9149 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
9150 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
9151 pAdapter->sessionId)
9152 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
9153 uint8_t *mac;
9154 mac =
9155 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
9156 hddLog(LOG1,
9157 "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d "
9158 MAC_ADDRESS_STR, __func__,
9159 pHddCtx->tdlsConnInfo[staIdx].staId,
9160 pAdapter->sessionId,
9161 MAC_ADDR_ARRAY(mac));
9162 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
9163 (pAdapter),
9164 pAdapter->sessionId, mac);
9165 }
9166 }
9167#endif
9168 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"),
9169 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009170 hdd_info("Disconnect request from user space with reason: %s",
9171 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172 status = wlan_hdd_disconnect(pAdapter, reasonCode);
9173 if (0 != status) {
9174 hddLog(LOGE,
9175 FL("failure, returned %d"), status);
9176 return -EINVAL;
9177 }
9178 } else {
9179 hddLog(LOGE,
9180 FL("unexpected cfg disconnect called while in state (%d)"),
9181 pHddStaCtx->conn_info.connState);
9182 }
9183
9184 return status;
9185}
9186
9187/**
9188 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9189 * @wiphy: Pointer to wiphy
9190 * @dev: Pointer to network device
9191 * @reason: Disconnect reason code
9192 *
9193 * Return: 0 for success, non-zero for failure
9194 */
9195static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9196 struct net_device *dev, u16 reason)
9197{
9198 int ret;
9199 cds_ssr_protect(__func__);
9200 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
9201 cds_ssr_unprotect(__func__);
9202
9203 return ret;
9204}
9205
9206/**
9207 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
9208 * @pAdapter: Pointer to adapter
9209 * @param: Pointer to IBSS parameters
9210 *
9211 * This function is used to initialize the security settings in IBSS mode
9212 *
9213 * Return: 0 for success, non-zero for failure
9214 */
9215static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
9216 struct cfg80211_ibss_params
9217 *params)
9218{
9219 int status = 0;
9220 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9221 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9222 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9223
9224 ENTER();
9225
9226 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
9227 cdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
9228 pHddStaCtx->ibss_enc_key_installed = 0;
9229
9230 if (params->ie_len && (NULL != params->ie)) {
9231 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9232 params->ie_len, WLAN_EID_RSN)) {
9233 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9234 encryptionType = eCSR_ENCRYPT_TYPE_AES;
9235 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
9236 tDot11fIEWPA dot11WPAIE;
9237 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9238 u8 *ie;
9239
9240 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
9241 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9242 params->ie_len,
9243 DOT11F_EID_WPA);
9244 if (NULL != ie) {
9245 pWextState->wpaVersion =
9246 IW_AUTH_WPA_VERSION_WPA;
9247 /* Unpack the WPA IE */
9248 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
9249 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
9250 &ie[2 + 4],
9251 ie[1] - 4, &dot11WPAIE);
9252 /*Extract the multicast cipher, the encType for unicast
9253 cipher for wpa-none is none */
9254 encryptionType =
9255 hdd_translate_wpa_to_csr_encryption_type
9256 (dot11WPAIE.multicast_cipher);
9257 }
9258 }
9259
9260 status =
9261 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
9262 params->ie_len);
9263
9264 if (0 > status) {
9265 hddLog(LOGE, FL("failed to parse WPA/RSN IE"));
9266 return status;
9267 }
9268 }
9269
9270 pWextState->roamProfile.AuthType.authType[0] =
9271 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
9272
9273 if (params->privacy) {
9274 /* Security enabled IBSS, At this time there is no information
9275 * available about the security paramters, so initialise the
9276 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
9277 * The correct security parameters will be updated later in
9278 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
9279 * set inorder enable privacy bit in beacons
9280 */
9281
9282 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9283 }
9284 hddLog(LOG2, FL("encryptionType=%d"), encryptionType);
9285 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
9286 pWextState->roamProfile.EncryptionType.numEntries = 1;
9287 pWextState->roamProfile.EncryptionType.encryptionType[0] =
9288 encryptionType;
9289 return status;
9290}
9291
9292/**
9293 * __wlan_hdd_cfg80211_join_ibss() - join ibss
9294 * @wiphy: Pointer to wiphy
9295 * @dev: Pointer to network device
9296 * @param: Pointer to IBSS join parameters
9297 *
9298 * This function is used to create/join an IBSS network
9299 *
9300 * Return: 0 for success, non-zero for failure
9301 */
9302static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9303 struct net_device *dev,
9304 struct cfg80211_ibss_params *params)
9305{
9306 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9307 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9308 tCsrRoamProfile *pRoamProfile;
9309 int status;
9310 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9311 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +05309312 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009313 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009314
9315 ENTER();
9316
Anurag Chouhan6d760662016-02-20 16:05:43 +05309317 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009318 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9319 return -EINVAL;
9320 }
9321
Anurag Chouhan6d760662016-02-20 16:05:43 +05309322 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009323 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
9324 pAdapter->sessionId, pAdapter->device_mode));
9325 hddLog(LOG1, FL("Device_mode %s(%d)"),
9326 hdd_device_mode_to_string(pAdapter->device_mode),
9327 pAdapter->device_mode);
9328
9329 status = wlan_hdd_validate_context(pHddCtx);
9330
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309331 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009332 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009333
9334 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05309335 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009336 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9337 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9338 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9339 int indx;
9340
9341 /* Get channel number */
9342 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009343 params->
9344 chandef.
9345 chan->
9346 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347
9348 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9349 validChan, &numChans)) {
9350 hddLog(LOGE, FL("No valid channel list"));
9351 return -EOPNOTSUPP;
9352 }
9353
9354 for (indx = 0; indx < numChans; indx++) {
9355 if (channelNum == validChan[indx]) {
9356 break;
9357 }
9358 }
9359 if (indx >= numChans) {
9360 hddLog(LOGE,
9361 FL("Not valid Channel %d"), channelNum);
9362 return -EINVAL;
9363 }
9364 }
9365
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009366 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009367 HW_MODE_20_MHZ)) {
9368 hdd_err("This concurrency combination is not allowed");
9369 return -ECONNREFUSED;
9370 }
9371 if (pHddCtx->config->policy_manager_enabled) {
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05309372 status = cdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309373 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009374 hdd_err("ERR: clear event failed");
9375
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05309376 status = cds_current_connections_update(pAdapter->sessionId,
9377 channelNum,
9378 CDS_UPDATE_REASON_JOIN_IBSS);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309379 if (QDF_STATUS_E_FAILURE == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380 hdd_err("ERROR: connections update failed!!");
9381 return -EINVAL;
9382 }
9383
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309384 if (QDF_STATUS_SUCCESS == status) {
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05309385 status = cdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309386 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009387 hdd_err("ERROR: cdf wait for event failed!!");
9388 return -EINVAL;
9389 }
9390 }
9391 }
9392
9393 /*Try disconnecting if already in connected state */
9394 status = wlan_hdd_try_disconnect(pAdapter);
9395 if (0 > status) {
9396 hddLog(LOGE,
9397 FL("Failed to disconnect the existing IBSS connection"));
9398 return -EALREADY;
9399 }
9400
9401 pRoamProfile = &pWextState->roamProfile;
9402
9403 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
9404 hddLog(LOGE,
9405 FL("Interface type is not set to IBSS"));
9406 return -EINVAL;
9407 }
9408
9409 /* enable selected protection checks in IBSS mode */
9410 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
9411
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309412 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009413 WNI_CFG_IBSS_ATIM_WIN_SIZE,
9414 pHddCtx->config->
9415 ibssATIMWinSize)) {
9416 hddLog(LOGE,
9417 FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"));
9418 }
9419
9420 /* BSSID is provided by upper layers hence no need to AUTO generate */
9421 if (NULL != params->bssid) {
9422 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309423 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 hddLog(LOGE,
9425 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
9426 return -EIO;
9427 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05309428 cdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
9430 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309431 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009432 hddLog(LOGE,
9433 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
9434 return -EIO;
9435 }
9436 cdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
9437 }
9438 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
9439 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
9440 pRoamProfile->beaconInterval = params->beacon_interval;
9441 else {
9442 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
9443 hddLog(LOG2,
9444 FL("input beacon interval %d TU is invalid, use default %d TU"),
9445 params->beacon_interval, pRoamProfile->beaconInterval);
9446 }
9447
9448 /* Set Channel */
9449 if (channelNum) {
9450 /* Set the Operational Channel */
9451 hddLog(LOG2, FL("set channel %d"), channelNum);
9452 pRoamProfile->ChannelInfo.numOfChannels = 1;
9453 pHddStaCtx->conn_info.operationChannel = channelNum;
9454 pRoamProfile->ChannelInfo.ChannelList =
9455 &pHddStaCtx->conn_info.operationChannel;
9456 }
9457
9458 /* Initialize security parameters */
9459 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
9460 if (status < 0) {
9461 hddLog(LOGE,
9462 FL("failed to set security parameters"));
9463 return status;
9464 }
9465
9466 /* Issue connect start */
9467 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
9468 params->ssid_len,
9469 bssid.bytes,
9470 NULL,
9471 pHddStaCtx->conn_info.
9472 operationChannel);
9473
9474 if (0 > status) {
9475 hddLog(LOGE, FL("connect failed"));
9476 return status;
9477 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309478 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479 return 0;
9480}
9481
9482/**
9483 * wlan_hdd_cfg80211_join_ibss() - join ibss
9484 * @wiphy: Pointer to wiphy
9485 * @dev: Pointer to network device
9486 * @param: Pointer to IBSS join parameters
9487 *
9488 * This function is used to create/join an IBSS network
9489 *
9490 * Return: 0 for success, non-zero for failure
9491 */
9492static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9493 struct net_device *dev,
9494 struct cfg80211_ibss_params *params)
9495{
9496 int ret = 0;
9497
9498 cds_ssr_protect(__func__);
9499 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
9500 cds_ssr_unprotect(__func__);
9501
9502 return ret;
9503}
9504
9505/**
9506 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
9507 * @wiphy: Pointer to wiphy
9508 * @dev: Pointer to network device
9509 *
9510 * This function is used to leave an IBSS network
9511 *
9512 * Return: 0 for success, non-zero for failure
9513 */
9514static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9515 struct net_device *dev)
9516{
9517 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9518 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9519 tCsrRoamProfile *pRoamProfile;
9520 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9521 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309522 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +05309523 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009524
9525 ENTER();
9526
Anurag Chouhan6d760662016-02-20 16:05:43 +05309527 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9529 return -EINVAL;
9530 }
9531
Anurag Chouhan6d760662016-02-20 16:05:43 +05309532 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
9534 pAdapter->sessionId,
9535 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
9536 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309537 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009538 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009539
9540 hddLog(LOG1, FL("Device_mode %s(%d)"),
9541 hdd_device_mode_to_string(pAdapter->device_mode),
9542 pAdapter->device_mode);
9543 if (NULL == pWextState) {
9544 hddLog(LOGE, FL("Data Storage Corruption"));
9545 return -EIO;
9546 }
9547
9548 pRoamProfile = &pWextState->roamProfile;
9549
9550 /* Issue disconnect only if interface type is set to IBSS */
9551 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
9552 hddLog(LOGE,
9553 FL("BSS Type is not set to IBSS"));
9554 return -EINVAL;
9555 }
9556
9557 /* Issue Disconnect request */
9558 INIT_COMPLETION(pAdapter->disconnect_comp_var);
9559 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9560 pAdapter->sessionId,
9561 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309562 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009563 hddLog(LOGE,
9564 FL("sme_roam_disconnect failed hal_status(%d)"),
9565 hal_status);
9566 return -EAGAIN;
9567 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +05309568
9569 /* wait for mc thread to cleanup and then return to upper stack
9570 * so by the time upper layer calls the change interface, we are
9571 * all set to proceed further
9572 */
9573 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
9574 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9575 if (!rc) {
9576 hdd_err("Failed to disconnect, timed out");
9577 return -ETIMEDOUT;
9578 }
9579
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309580 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 return 0;
9582}
9583
9584/**
9585 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
9586 * @wiphy: Pointer to wiphy
9587 * @dev: Pointer to network device
9588 *
9589 * This function is used to leave an IBSS network
9590 *
9591 * Return: 0 for success, non-zero for failure
9592 */
9593static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9594 struct net_device *dev)
9595{
9596 int ret = 0;
9597
9598 cds_ssr_protect(__func__);
9599 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
9600 cds_ssr_unprotect(__func__);
9601
9602 return ret;
9603}
9604
9605/**
9606 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9607 * @wiphy: Pointer to wiphy
9608 * @changed: Parameters changed
9609 *
9610 * This function is used to set the phy parameters. RTS Threshold/FRAG
9611 * Threshold/Retry Count etc.
9612 *
9613 * Return: 0 for success, non-zero for failure
9614 */
9615static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
9616 u32 changed)
9617{
9618 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9619 tHalHandle hHal = pHddCtx->hHal;
9620 int status;
9621
9622 ENTER();
9623
Anurag Chouhan6d760662016-02-20 16:05:43 +05309624 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009625 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9626 return -EINVAL;
9627 }
9628
Anurag Chouhan6d760662016-02-20 16:05:43 +05309629 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009630 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
9631 NO_SESSION, wiphy->rts_threshold));
9632 status = wlan_hdd_validate_context(pHddCtx);
9633
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309634 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009636
9637 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
9638 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
9639 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
9640
9641 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
9642 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
9643 hddLog(LOGE,
9644 FL("Invalid RTS Threshold value %u"),
9645 rts_threshold);
9646 return -EINVAL;
9647 }
9648
9649 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
9650 rts_threshold)) {
9651 hddLog(LOGE,
9652 FL("sme_cfg_set_int failed for rts_threshold value %u"),
9653 rts_threshold);
9654 return -EIO;
9655 }
9656
9657 hddLog(LOG2, FL("set rts threshold %u"), rts_threshold);
9658 }
9659
9660 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
9661 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
9662 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
9663 wiphy->frag_threshold;
9664
9665 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
9666 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
9667 hddLog(LOGE,
9668 FL("Invalid frag_threshold value %hu"),
9669 frag_threshold);
9670 return -EINVAL;
9671 }
9672
9673 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
9674 frag_threshold)) {
9675 hddLog(LOGE,
9676 FL("sme_cfg_set_int failed for frag_threshold value %hu"),
9677 frag_threshold);
9678 return -EIO;
9679 }
9680
9681 hddLog(LOG2, FL("set frag threshold %hu"), frag_threshold);
9682 }
9683
9684 if ((changed & WIPHY_PARAM_RETRY_SHORT)
9685 || (changed & WIPHY_PARAM_RETRY_LONG)) {
9686 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
9687 wiphy->retry_short : wiphy->retry_long;
9688
9689 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
9690 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
9691 hddLog(LOGE,
9692 FL("Invalid Retry count %hu"), retry_value);
9693 return -EINVAL;
9694 }
9695
9696 if (changed & WIPHY_PARAM_RETRY_SHORT) {
9697 if (0 != sme_cfg_set_int(hHal,
9698 WNI_CFG_LONG_RETRY_LIMIT,
9699 retry_value)) {
9700 hddLog(LOGE,
9701 FL("sme_cfg_set_int failed for long retry count %hu"),
9702 retry_value);
9703 return -EIO;
9704 }
9705 hddLog(LOG2,
9706 FL("set long retry count %hu"), retry_value);
9707 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
9708 if (0 != sme_cfg_set_int(hHal,
9709 WNI_CFG_SHORT_RETRY_LIMIT,
9710 retry_value)) {
9711 hddLog(LOGE,
9712 FL("sme_cfg_set_int failed for short retry count %hu"),
9713 retry_value);
9714 return -EIO;
9715 }
9716 hddLog(LOG2,
9717 FL("set short retry count %hu"), retry_value);
9718 }
9719 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309720 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009721 return 0;
9722}
9723
9724/**
9725 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9726 * @wiphy: Pointer to wiphy
9727 * @changed: Parameters changed
9728 *
9729 * Return: 0 for success, non-zero for failure
9730 */
9731static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
9732{
9733 int ret;
9734
9735 cds_ssr_protect(__func__);
9736 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
9737 cds_ssr_unprotect(__func__);
9738
9739 return ret;
9740}
9741
9742/**
9743 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
9744 * key
9745 * @wiphy: Pointer to wiphy
9746 * @dev: Pointer to network device
9747 * @key_index: Key index
9748 *
9749 * Return: 0
9750 */
9751static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9752 struct net_device *netdev,
9753 u8 key_index)
9754{
9755 ENTER();
9756 return 0;
9757}
9758
9759/**
9760 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
9761 * wlan_hdd_set_default_mgmt_key
9762 * @wiphy: pointer to wiphy
9763 * @netdev: pointer to net_device structure
9764 * @key_index: key index
9765 *
9766 * Return: 0 on success, error number on failure
9767 */
9768static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9769 struct net_device *netdev,
9770 u8 key_index)
9771{
9772 int ret;
9773
9774 cds_ssr_protect(__func__);
9775 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
9776 cds_ssr_unprotect(__func__);
9777
9778 return ret;
9779}
9780
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009781/**
9782 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
9783 * @wiphy: Pointer to wiphy
9784 * @dev: Pointer to network device
9785 * @params: Pointer to tx queue parameters
9786 *
9787 * Return: 0
9788 */
9789static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
9790 struct net_device *dev,
9791 struct ieee80211_txq_params *params)
9792{
9793 ENTER();
9794 return 0;
9795}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009796
9797/**
9798 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
9799 * @wiphy: pointer to wiphy
9800 * @netdev: pointer to net_device structure
9801 * @params: pointer to ieee80211_txq_params
9802 *
9803 * Return: 0 on success, error number on failure
9804 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009805static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
9806 struct net_device *dev,
9807 struct ieee80211_txq_params *params)
9808{
9809 int ret;
9810
9811 cds_ssr_protect(__func__);
9812 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
9813 cds_ssr_unprotect(__func__);
9814
9815 return ret;
9816}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009817
9818/**
9819 * __wlan_hdd_cfg80211_del_station() - delete station v2
9820 * @wiphy: Pointer to wiphy
9821 * @param: Pointer to delete station parameter
9822 *
9823 * Return: 0 for success, non-zero for failure
9824 */
9825static
9826int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9827 struct net_device *dev,
9828 struct tagCsrDelStaParams *pDelStaParams)
9829{
9830 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9831 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309832 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009833 hdd_hostapd_state_t *hapd_state;
9834 int status;
9835 uint8_t staId;
9836 uint8_t *mac;
9837
9838 ENTER();
9839
Anurag Chouhan6d760662016-02-20 16:05:43 +05309840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009841 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9842 return -EINVAL;
9843 }
9844
Anurag Chouhan6d760662016-02-20 16:05:43 +05309845 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009846 TRACE_CODE_HDD_CFG80211_DEL_STA,
9847 pAdapter->sessionId, pAdapter->device_mode));
9848
9849 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9850 status = wlan_hdd_validate_context(pHddCtx);
9851
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309852 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009853 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854
9855 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
9856
9857 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
9858 (WLAN_HDD_P2P_GO == pAdapter->device_mode)) {
9859
9860 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9861 if (!hapd_state) {
9862 hddLog(LOGE, "%s: Hostapd State is Null", __func__);
9863 return 0;
9864 }
9865
Anurag Chouhan6d760662016-02-20 16:05:43 +05309866 if (cdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009867 uint16_t i;
9868 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
9869 if ((pAdapter->aStaInfo[i].isUsed) &&
9870 (!pAdapter->aStaInfo[i].
9871 isDeauthInProgress)) {
9872 cdf_mem_copy(
9873 mac,
9874 pAdapter->aStaInfo[i].
9875 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309876 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009877 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
9878 hdd_ipa_wlan_evt(pAdapter,
9879 pAdapter->
9880 aStaInfo[i].
9881 ucSTAId,
9882 WLAN_CLIENT_DISCONNECT,
9883 mac);
9884 }
9885 hddLog(LOG1,
9886 FL("Delete STA with MAC::"
9887 MAC_ADDRESS_STR),
9888 MAC_ADDR_ARRAY(mac));
9889
9890 if (pHddCtx->dev_dfs_cac_status ==
9891 DFS_CAC_IN_PROGRESS)
9892 goto fn_end;
9893
Anurag Chouhance0dc992016-02-16 18:18:03 +05309894 qdf_event_reset(&hapd_state->cdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009895 hdd_softap_sta_disassoc(pAdapter,
9896 mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309897 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009898 hdd_softap_sta_deauth(pAdapter,
9899 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309900 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009901 pAdapter->aStaInfo[i].
9902 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309903 qdf_status =
9904 qdf_wait_single_event(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009905 &hapd_state->cdf_event,
9906 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309907 if (!QDF_IS_STATUS_SUCCESS(
9908 qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009909 hddLog(LOGE,
9910 "%s: Deauth wait time expired",
9911 __func__);
9912 }
9913 }
9914 }
9915 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309916 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009917 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309918 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009919 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309920 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009921 hddLog(LOG1,
9922 FL("Skip DEL STA as this is not used::"
9923 MAC_ADDRESS_STR),
9924 MAC_ADDR_ARRAY(mac));
9925 return -ENOENT;
9926 }
9927
9928 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
9929 hdd_ipa_wlan_evt(pAdapter, staId,
9930 WLAN_CLIENT_DISCONNECT, mac);
9931 }
9932
9933 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
9934 true) {
9935 hddLog(LOG1,
9936 FL("Skip DEL STA as deauth is in progress::"
9937 MAC_ADDRESS_STR),
9938 MAC_ADDR_ARRAY(mac));
9939 return -ENOENT;
9940 }
9941
9942 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
9943
9944 hddLog(LOG1,
9945 FL("Delete STA with MAC::" MAC_ADDRESS_STR),
9946 MAC_ADDR_ARRAY(mac));
9947
9948 /* Case: SAP in ACS selected DFS ch and client connected
9949 * Now Radar detected. Then if random channel is another
9950 * DFS ch then new CAC is initiated and no TX allowed.
9951 * So do not send any mgmt frames as it will timeout
9952 * during CAC.
9953 */
9954
9955 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
9956 goto fn_end;
9957
Anurag Chouhance0dc992016-02-16 18:18:03 +05309958 qdf_event_reset(&hapd_state->cdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009959 hdd_softap_sta_disassoc(pAdapter, mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309960 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309962 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009963 pAdapter->aStaInfo[staId].isDeauthInProgress =
9964 false;
9965 hddLog(LOG1,
9966 FL("STA removal failed for ::"
9967 MAC_ADDRESS_STR),
9968 MAC_ADDR_ARRAY(mac));
9969 return -ENOENT;
9970 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +05309971 qdf_status = qdf_wait_single_event(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 &hapd_state->cdf_event,
9973 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309974 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975 hddLog(LOGE,
9976 "%s: Deauth wait time expired",
9977 __func__);
9978 }
9979 }
9980 }
9981
9982fn_end:
9983 EXIT();
9984 return 0;
9985}
9986
9987#ifdef CFG80211_DEL_STA_V2
9988/**
9989 * wlan_hdd_cfg80211_del_station() - delete station v2
9990 * @wiphy: Pointer to wiphy
9991 * @param: Pointer to delete station parameter
9992 *
9993 * Return: 0 for success, non-zero for failure
9994 */
9995int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9996 struct net_device *dev,
9997 struct station_del_parameters *param)
9998#else
9999/**
10000 * wlan_hdd_cfg80211_del_station() - delete station
10001 * @wiphy: Pointer to wiphy
10002 * @mac: Pointer to station mac address
10003 *
10004 * Return: 0 for success, non-zero for failure
10005 */
10006#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10007int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10008 struct net_device *dev,
10009 const uint8_t *mac)
10010#else
10011int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10012 struct net_device *dev,
10013 uint8_t *mac)
10014#endif
10015#endif
10016{
10017 int ret;
10018 struct tagCsrDelStaParams delStaParams;
10019
10020 cds_ssr_protect(__func__);
10021#ifdef CFG80211_DEL_STA_V2
10022 if (NULL == param) {
10023 hddLog(LOGE, FL("Invalid argumet passed"));
10024 return -EINVAL;
10025 }
10026 wlansap_populate_del_sta_params(param->mac, param->reason_code,
10027 param->subtype, &delStaParams);
10028#else
10029 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
10030 (SIR_MAC_MGMT_DEAUTH >> 4),
10031 &delStaParams);
10032#endif
10033 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
10034 cds_ssr_unprotect(__func__);
10035
10036 return ret;
10037}
10038
10039/**
10040 * __wlan_hdd_cfg80211_add_station() - add station
10041 * @wiphy: Pointer to wiphy
10042 * @mac: Pointer to station mac address
10043 * @pmksa: Pointer to add station parameter
10044 *
10045 * Return: 0 for success, non-zero for failure
10046 */
10047static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10048 struct net_device *dev,
10049 const uint8_t *mac,
10050 struct station_parameters *params)
10051{
10052 int status = -EPERM;
10053#ifdef FEATURE_WLAN_TDLS
10054 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10055 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10056 u32 mask, set;
10057
10058 ENTER();
10059
Anurag Chouhan6d760662016-02-20 16:05:43 +053010060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10062 return -EINVAL;
10063 }
10064
Anurag Chouhan6d760662016-02-20 16:05:43 +053010065 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066 TRACE_CODE_HDD_CFG80211_ADD_STA,
10067 pAdapter->sessionId, params->listen_interval));
10068
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010069 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010071
10072 mask = params->sta_flags_mask;
10073
10074 set = params->sta_flags_set;
10075
10076 hddLog(LOG1, FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), mask, set,
10077 MAC_ADDR_ARRAY(mac));
10078
10079 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10080 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10081 status =
10082 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
10083 }
10084 }
10085#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010086 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010087 return status;
10088}
10089
10090/**
10091 * wlan_hdd_cfg80211_add_station() - add station
10092 * @wiphy: Pointer to wiphy
10093 * @mac: Pointer to station mac address
10094 * @pmksa: Pointer to add station parameter
10095 *
10096 * Return: 0 for success, non-zero for failure
10097 */
10098#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10099static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10100 struct net_device *dev,
10101 const uint8_t *mac,
10102 struct station_parameters *params)
10103#else
10104static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10105 struct net_device *dev, uint8_t *mac,
10106 struct station_parameters *params)
10107#endif
10108{
10109 int ret;
10110
10111 cds_ssr_protect(__func__);
10112 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
10113 cds_ssr_unprotect(__func__);
10114
10115 return ret;
10116}
10117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118/**
10119 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
10120 * @wiphy: Pointer to wiphy
10121 * @dev: Pointer to network device
10122 * @pmksa: Pointer to set pmksa parameter
10123 *
10124 * Return: 0 for success, non-zero for failure
10125 */
10126static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10127 struct net_device *dev,
10128 struct cfg80211_pmksa *pmksa)
10129{
10130 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10131 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10132 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010133 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134 int status;
10135 tPmkidCacheInfo pmk_id;
10136
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010137 ENTER();
10138
Anurag Chouhan6d760662016-02-20 16:05:43 +053010139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10141 return -EINVAL;
10142 }
10143
10144 if (!pmksa) {
10145 hddLog(LOGE, FL("pmksa is NULL"));
10146 return -EINVAL;
10147 }
10148
10149 if (!pmksa->bssid || !pmksa->pmkid) {
10150 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
10151 pmksa->bssid, pmksa->pmkid);
10152 return -EINVAL;
10153 }
10154
10155 hddLog(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR),
10156 MAC_ADDR_ARRAY(pmksa->bssid));
10157
10158 status = wlan_hdd_validate_context(pHddCtx);
10159
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010160 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010162
10163 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10164
Anurag Chouhan6d760662016-02-20 16:05:43 +053010165 cdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010166 cdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
10167
10168 /* Add to the PMKSA ID Cache in CSR */
10169 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
10170 &pmk_id, 1, false);
10171
Anurag Chouhan6d760662016-02-20 16:05:43 +053010172 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010173 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
10174 pAdapter->sessionId, result));
10175
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010176 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010177 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010178}
10179
10180/**
10181 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
10182 * @wiphy: Pointer to wiphy
10183 * @dev: Pointer to network device
10184 * @pmksa: Pointer to set pmksa parameter
10185 *
10186 * Return: 0 for success, non-zero for failure
10187 */
10188static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10189 struct net_device *dev,
10190 struct cfg80211_pmksa *pmksa)
10191{
10192 int ret;
10193
10194 cds_ssr_protect(__func__);
10195 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
10196 cds_ssr_unprotect(__func__);
10197
10198 return ret;
10199}
10200
10201/**
10202 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10203 * @wiphy: Pointer to wiphy
10204 * @dev: Pointer to network device
10205 * @pmksa: Pointer to pmksa parameter
10206 *
10207 * Return: 0 for success, non-zero for failure
10208 */
10209static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10210 struct net_device *dev,
10211 struct cfg80211_pmksa *pmksa)
10212{
10213 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10214 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10215 tHalHandle halHandle;
10216 int status = 0;
10217
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010218 ENTER();
10219
Anurag Chouhan6d760662016-02-20 16:05:43 +053010220 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10222 return -EINVAL;
10223 }
10224
10225 if (!pmksa) {
10226 hddLog(LOGE, FL("pmksa is NULL"));
10227 return -EINVAL;
10228 }
10229
10230 if (!pmksa->bssid) {
10231 hddLog(LOGE, FL("pmksa->bssid is NULL"));
10232 return -EINVAL;
10233 }
10234
10235 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR),
10236 MAC_ADDR_ARRAY(pmksa->bssid));
10237
10238 status = wlan_hdd_validate_context(pHddCtx);
10239
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010240 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010242
10243 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10244
Anurag Chouhan6d760662016-02-20 16:05:43 +053010245 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010246 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
10247 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010248 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010249 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250 sme_roam_del_pmkid_from_cache(halHandle,
10251 pAdapter->sessionId, pmksa->bssid,
10252 false)) {
10253 hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR),
10254 MAC_ADDR_ARRAY(pmksa->bssid));
10255 status = -EINVAL;
10256 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010257 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010258 return status;
10259}
10260
10261/**
10262 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10263 * @wiphy: Pointer to wiphy
10264 * @dev: Pointer to network device
10265 * @pmksa: Pointer to pmksa parameter
10266 *
10267 * Return: 0 for success, non-zero for failure
10268 */
10269static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10270 struct net_device *dev,
10271 struct cfg80211_pmksa *pmksa)
10272{
10273 int ret;
10274
10275 cds_ssr_protect(__func__);
10276 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
10277 cds_ssr_unprotect(__func__);
10278
10279 return ret;
10280
10281}
10282
10283/**
10284 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10285 * @wiphy: Pointer to wiphy
10286 * @dev: Pointer to network device
10287 *
10288 * Return: 0 for success, non-zero for failure
10289 */
10290static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10291 struct net_device *dev)
10292{
10293 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10294 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10295 tHalHandle halHandle;
10296 int status = 0;
10297
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010298 ENTER();
10299
Anurag Chouhan6d760662016-02-20 16:05:43 +053010300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10302 return -EINVAL;
10303 }
10304
10305 hddLog(LOGW, FL("Flushing PMKSA"));
10306
10307 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10308 status = wlan_hdd_validate_context(pHddCtx);
10309
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010310 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312
10313 /* Retrieve halHandle */
10314 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10315
10316 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010317 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
10319 true)) {
10320 hddLog(LOGE, FL("Cannot flush PMKIDCache"));
10321 status = -EINVAL;
10322 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010323 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 return status;
10325}
10326
10327/**
10328 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10329 * @wiphy: Pointer to wiphy
10330 * @dev: Pointer to network device
10331 *
10332 * Return: 0 for success, non-zero for failure
10333 */
10334static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10335 struct net_device *dev)
10336{
10337 int ret;
10338
10339 cds_ssr_protect(__func__);
10340 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
10341 cds_ssr_unprotect(__func__);
10342
10343 return ret;
10344}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010345
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080010346#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010347/**
10348 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
10349 * @wiphy: Pointer to wiphy
10350 * @dev: Pointer to network device
10351 * @ftie: Pointer to fast transition ie parameter
10352 *
10353 * Return: 0 for success, non-zero for failure
10354 */
10355static int
10356__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
10357 struct net_device *dev,
10358 struct cfg80211_update_ft_ies_params *ftie)
10359{
10360 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
10361 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10362 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10363 int status;
10364
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010365 ENTER();
10366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367 status = wlan_hdd_validate_context(hdd_ctx);
10368 if (status)
10369 return status;
10370
Anurag Chouhan6d760662016-02-20 16:05:43 +053010371 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10373 return -EINVAL;
10374 }
10375
Anurag Chouhan6d760662016-02-20 16:05:43 +053010376 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010377 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
10378 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
10379 /* Added for debug on reception of Re-assoc Req. */
10380 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
10381 hddLog(LOGE,
10382 FL("Called with Ie of length = %zu when not associated"),
10383 ftie->ie_len);
10384 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
10385 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010386 hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__,
10387 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010388
10389 /* Pass the received FT IEs to SME */
10390 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
10391 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010392 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010393 return 0;
10394}
10395
10396/**
10397 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
10398 * @wiphy: Pointer to wiphy
10399 * @dev: Pointer to network device
10400 * @ftie: Pointer to fast transition ie parameter
10401 *
10402 * Return: 0 for success, non-zero for failure
10403 */
10404static int
10405wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
10406 struct net_device *dev,
10407 struct cfg80211_update_ft_ies_params *ftie)
10408{
10409 int ret;
10410
10411 cds_ssr_protect(__func__);
10412 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
10413 cds_ssr_unprotect(__func__);
10414
10415 return ret;
10416}
10417#endif
10418
10419#ifdef WLAN_FEATURE_GTK_OFFLOAD
10420/**
10421 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
10422 * @callbackContext: Callback context
10423 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
10424 *
10425 * Callback rountine called upon receiving response for get offload info
10426 *
10427 * Return: none
10428 */
10429void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
10430 tpSirGtkOffloadGetInfoRspParams
10431 pGtkOffloadGetInfoRsp)
10432{
10433 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
10434 uint8_t tempReplayCounter[8];
10435 hdd_station_ctx_t *pHddStaCtx;
10436
10437 ENTER();
10438
10439 if (NULL == pAdapter) {
10440 hddLog(LOGE, FL("HDD adapter is Null"));
10441 return;
10442 }
10443
10444 if (NULL == pGtkOffloadGetInfoRsp) {
10445 hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null"));
10446 return;
10447 }
10448
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010449 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010450 hddLog(LOGE, FL("wlan Failed to get replay counter value"));
10451 return;
10452 }
10453
10454 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10455 /* Update replay counter */
10456 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
10457 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
10458
10459 {
10460 /* changing from little to big endian since supplicant
10461 * works on big endian format
10462 */
10463 int i;
10464 uint8_t *p =
10465 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
10466
10467 for (i = 0; i < 8; i++) {
10468 tempReplayCounter[7 - i] = (uint8_t) p[i];
10469 }
10470 }
10471
10472 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080010473 cfg80211_gtk_rekey_notify(pAdapter->dev,
10474 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010475 tempReplayCounter, GFP_KERNEL);
10476}
10477
10478/**
10479 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10480 * @wiphy: Pointer to wiphy
10481 * @dev: Pointer to network device
10482 * @data: Pointer to rekey data
10483 *
10484 * This function is used to offload GTK rekeying job to the firmware.
10485 *
10486 * Return: 0 for success, non-zero for failure
10487 */
10488int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10489 struct net_device *dev,
10490 struct cfg80211_gtk_rekey_data *data)
10491{
10492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10493 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10494 hdd_station_ctx_t *pHddStaCtx;
10495 tHalHandle hHal;
10496 int result;
10497 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010498 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010499
10500 ENTER();
10501
Anurag Chouhan6d760662016-02-20 16:05:43 +053010502 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10504 return -EINVAL;
10505 }
10506
Anurag Chouhan6d760662016-02-20 16:05:43 +053010507 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010508 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
10509 pAdapter->sessionId, pAdapter->device_mode));
10510
10511 result = wlan_hdd_validate_context(pHddCtx);
10512
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010513 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010514 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515
10516 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10517 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10518 if (NULL == hHal) {
10519 hddLog(LOGE, FL("HAL context is Null!!!"));
10520 return -EAGAIN;
10521 }
10522
10523 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
10524 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
10525 NL80211_KCK_LEN);
10526 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
10527 NL80211_KEK_LEN);
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080010528 cdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
10529 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010530 {
10531 /* changing from big to little endian since driver
10532 * works on little endian format
10533 */
10534 uint8_t *p =
10535 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
10536 ullKeyReplayCounter;
10537 int i;
10538
10539 for (i = 0; i < 8; i++) {
10540 p[7 - i] = data->replay_ctr[i];
10541 }
10542 }
10543
10544 if (true == pHddCtx->hdd_wlan_suspended) {
10545 /* if wlan is suspended, enable GTK offload directly from here */
10546 memcpy(&hddGtkOffloadReqParams,
10547 &pHddStaCtx->gtkOffloadReqParams,
10548 sizeof(tSirGtkOffloadParams));
10549 status =
10550 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
10551 pAdapter->sessionId);
10552
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010553 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554 hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"),
10555 status);
10556 return -EINVAL;
10557 }
10558 hddLog(LOG1, FL("sme_set_gtk_offload successful"));
10559 } else {
10560 hddLog(LOG1,
10561 FL("wlan not suspended GTKOffload request is stored"));
10562 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010563 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564 return result;
10565}
10566
10567/**
10568 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10569 * @wiphy: Pointer to wiphy
10570 * @dev: Pointer to network device
10571 * @data: Pointer to rekey data
10572 *
10573 * This function is used to offload GTK rekeying job to the firmware.
10574 *
10575 * Return: 0 for success, non-zero for failure
10576 */
10577int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10578 struct net_device *dev,
10579 struct cfg80211_gtk_rekey_data *data)
10580{
10581 int ret;
10582
10583 cds_ssr_protect(__func__);
10584 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
10585 cds_ssr_unprotect(__func__);
10586
10587 return ret;
10588}
10589#endif /*WLAN_FEATURE_GTK_OFFLOAD */
10590
10591/**
10592 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
10593 * @wiphy: Pointer to wiphy
10594 * @dev: Pointer to network device
10595 * @param: Pointer to access control parameter
10596 *
10597 * Return: 0 for success, non-zero for failure
10598 */
10599static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10600 struct net_device *dev,
10601 const struct cfg80211_acl_data *params)
10602{
10603 int i;
10604 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10605 hdd_hostapd_state_t *pHostapdState;
10606 tsap_Config_t *pConfig;
10607 v_CONTEXT_t p_cds_context = NULL;
10608 hdd_context_t *pHddCtx;
10609 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010610 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010611
10612 ENTER();
10613
Anurag Chouhan6d760662016-02-20 16:05:43 +053010614 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010615 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10616 return -EINVAL;
10617 }
10618
10619 if (NULL == params) {
10620 hddLog(LOGE, FL("params is Null"));
10621 return -EINVAL;
10622 }
10623
10624 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10625 status = wlan_hdd_validate_context(pHddCtx);
10626
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010627 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010628 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010629
10630 p_cds_context = pHddCtx->pcds_context;
10631 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10632
10633 if (NULL == pHostapdState) {
10634 hddLog(LOGE, FL("pHostapdState is Null"));
10635 return -EINVAL;
10636 }
10637
10638 hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy,
10639 params->n_acl_entries);
10640
Anurag Chouhan6d760662016-02-20 16:05:43 +053010641 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010642 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
10643 pAdapter->sessionId, pAdapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 if (WLAN_HDD_SOFTAP == pAdapter->device_mode) {
10645 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
10646
10647 /* default value */
10648 pConfig->num_accept_mac = 0;
10649 pConfig->num_deny_mac = 0;
10650
10651 /**
10652 * access control policy
10653 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
10654 * listed in hostapd.deny file.
10655 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
10656 * listed in hostapd.accept file.
10657 */
10658 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
10659 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
10660 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
10661 params->acl_policy) {
10662 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
10663 } else {
10664 hddLog(LOGE, FL("Acl Policy : %d is not supported"),
10665 params->acl_policy);
10666 return -ENOTSUPP;
10667 }
10668
10669 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
10670 pConfig->num_accept_mac = params->n_acl_entries;
10671 for (i = 0; i < params->n_acl_entries; i++) {
10672 hddLog(LOG1,
10673 FL("** Add ACL MAC entry %i in WhiletList :"
10674 MAC_ADDRESS_STR), i,
10675 MAC_ADDR_ARRAY(
10676 params->mac_addrs[i].addr));
10677
10678 cdf_mem_copy(&pConfig->accept_mac[i],
10679 params->mac_addrs[i].addr,
10680 sizeof(qcmacaddr));
10681 }
10682 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
10683 pConfig->num_deny_mac = params->n_acl_entries;
10684 for (i = 0; i < params->n_acl_entries; i++) {
10685 hddLog(LOG1,
10686 FL("** Add ACL MAC entry %i in BlackList :"
10687 MAC_ADDRESS_STR), i,
10688 MAC_ADDR_ARRAY(
10689 params->mac_addrs[i].addr));
10690
10691 cdf_mem_copy(&pConfig->deny_mac[i],
10692 params->mac_addrs[i].addr,
10693 sizeof(qcmacaddr));
10694 }
10695 }
10696#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010697 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010698 wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
10699 pConfig);
10700#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010701 qdf_status = wlansap_set_mac_acl(p_cds_context, pConfig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010702#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010703 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 hddLog(LOGE, FL("SAP Set Mac Acl fail"));
10705 return -EINVAL;
10706 }
10707 } else {
10708 hddLog(LOG1, FL("Invalid device_mode %s(%d)"),
10709 hdd_device_mode_to_string(pAdapter->device_mode),
10710 pAdapter->device_mode);
10711 return -EINVAL;
10712 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010713 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010714 return 0;
10715}
10716
10717/**
10718 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
10719 * __wlan_hdd_cfg80211_set_mac_acl
10720 * @wiphy: pointer to wiphy structure
10721 * @dev: pointer to net_device
10722 * @params: pointer to cfg80211_acl_data
10723 *
10724 * Return; 0 on success, error number otherwise
10725 */
10726static int
10727wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10728 struct net_device *dev,
10729 const struct cfg80211_acl_data *params)
10730{
10731 int ret;
10732
10733 cds_ssr_protect(__func__);
10734 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
10735 cds_ssr_unprotect(__func__);
10736
10737 return ret;
10738}
10739
10740#ifdef WLAN_NL80211_TESTMODE
10741#ifdef FEATURE_WLAN_LPHB
10742/**
10743 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
10744 * @pHddCtx: Pointer to hdd context
10745 * @lphbInd: Pointer to low power heart beat indication parameter
10746 *
10747 * Return: none
10748 */
10749void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
10750{
10751 struct sk_buff *skb;
10752
10753 hddLog(LOGE, FL("LPHB indication arrived"));
10754
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010755 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010756 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757
10758 if (NULL == lphbInd) {
10759 hddLog(LOGE, FL("invalid argument lphbInd"));
10760 return;
10761 }
10762
10763 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
10764 wiphy, sizeof(tSirLPHBInd),
10765 GFP_ATOMIC);
10766 if (!skb) {
10767 hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail"));
10768 return;
10769 }
10770
10771 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
10772 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail"));
10773 goto nla_put_failure;
10774 }
10775 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
10776 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail"));
10777 goto nla_put_failure;
10778 }
10779 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
10780 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail"));
10781 goto nla_put_failure;
10782 }
10783 cfg80211_testmode_event(skb, GFP_ATOMIC);
10784 return;
10785
10786nla_put_failure:
10787 hddLog(LOGE, FL("NLA Put fail"));
10788 kfree_skb(skb);
10789
10790 return;
10791}
10792#endif /* FEATURE_WLAN_LPHB */
10793
10794/**
10795 * __wlan_hdd_cfg80211_testmode() - test mode
10796 * @wiphy: Pointer to wiphy
10797 * @data: Data pointer
10798 * @len: Data length
10799 *
10800 * Return: 0 for success, non-zero for failure
10801 */
10802static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10803 void *data, int len)
10804{
10805 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
10806 int err;
10807 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10808
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010809 ENTER();
10810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010811 err = wlan_hdd_validate_context(pHddCtx);
10812 if (err)
10813 return err;
10814
10815 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
10816 len, wlan_hdd_tm_policy);
10817 if (err) {
10818 hddLog(LOGE, FL("Testmode INV ATTR"));
10819 return err;
10820 }
10821
10822 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
10823 hddLog(LOGE, FL("Testmode INV CMD"));
10824 return -EINVAL;
10825 }
10826
Anurag Chouhan6d760662016-02-20 16:05:43 +053010827 MTRACE(cdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010828 TRACE_CODE_HDD_CFG80211_TESTMODE,
10829 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010830 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
10831#ifdef FEATURE_WLAN_LPHB
10832 /* Low Power Heartbeat configuration request */
10833 case WLAN_HDD_TM_CMD_WLAN_HB:
10834 {
10835 int buf_len;
10836 void *buf;
10837 tSirLPHBReq *hb_params = NULL;
10838 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010839 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840
10841 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
10842 hddLog(LOGE, FL("Testmode INV DATA"));
10843 return -EINVAL;
10844 }
10845
10846 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
10847 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
10848
10849 hb_params_temp = (tSirLPHBReq *) buf;
10850 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
10851 && (hb_params_temp->params.lphbTcpParamReq.
10852 timePeriodSec == 0))
10853 return -EINVAL;
10854
10855 hb_params =
10856 (tSirLPHBReq *) cdf_mem_malloc(sizeof(tSirLPHBReq));
10857 if (NULL == hb_params) {
10858 hddLog(LOGE, FL("Request Buffer Alloc Fail"));
10859 return -ENOMEM;
10860 }
10861
10862 cdf_mem_copy(hb_params, buf, buf_len);
10863 smeStatus =
10864 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
10865 hb_params,
10866 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010867 if (QDF_STATUS_SUCCESS != smeStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868 hddLog(LOGE, "LPHB Config Fail, disable");
10869 cdf_mem_free(hb_params);
10870 }
10871 return 0;
10872 }
10873#endif /* FEATURE_WLAN_LPHB */
10874
10875#if defined(QCA_WIFI_FTM)
10876 case WLAN_HDD_TM_CMD_WLAN_FTM:
10877 {
10878 int buf_len;
10879 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010880 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
10882 hddLog(LOGE,
10883 FL
10884 ("WLAN_HDD_TM_ATTR_DATA attribute is invalid"));
10885 return -EINVAL;
10886 }
10887
10888 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
10889 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
10890
10891 pr_info("****FTM Tx cmd len = %d*****\n", buf_len);
10892
10893 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
10894
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010895 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010896 err = -EBUSY;
10897 break;
10898 }
10899#endif
10900
10901 default:
10902 hddLog(LOGE, FL("command %d not supported"),
10903 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
10904 return -EOPNOTSUPP;
10905 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010906 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 return err;
10908}
10909
10910/**
10911 * wlan_hdd_cfg80211_testmode() - test mode
10912 * @wiphy: Pointer to wiphy
10913 * @dev: Pointer to network device
10914 * @data: Data pointer
10915 * @len: Data length
10916 *
10917 * Return: 0 for success, non-zero for failure
10918 */
10919static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10920#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
10921 struct wireless_dev *wdev,
10922#endif
10923 void *data, int len)
10924{
10925 int ret;
10926
10927 cds_ssr_protect(__func__);
10928 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
10929 cds_ssr_unprotect(__func__);
10930
10931 return ret;
10932}
10933
10934#if defined(QCA_WIFI_FTM)
10935/**
10936 * wlan_hdd_testmode_rx_event() - test mode rx event handler
10937 * @buf: Pointer to buffer
10938 * @buf_len: Buffer length
10939 *
10940 * Return: none
10941 */
10942void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
10943{
10944 struct sk_buff *skb;
10945 hdd_context_t *hdd_ctx;
10946
10947 if (!buf || !buf_len) {
Anurag Chouhan6d760662016-02-20 16:05:43 +053010948 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010949 "%s: buf or buf_len invalid, buf = %p buf_len = %zu",
10950 __func__, buf, buf_len);
10951 return;
10952 }
10953
Anurag Chouhan6d760662016-02-20 16:05:43 +053010954 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955 if (!hdd_ctx) {
Anurag Chouhan6d760662016-02-20 16:05:43 +053010956 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 "%s: hdd context invalid", __func__);
10958 return;
10959 }
10960
10961 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
10962 buf_len, GFP_KERNEL);
10963 if (!skb) {
Anurag Chouhan6d760662016-02-20 16:05:43 +053010964 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965 "%s: failed to allocate testmode rx skb!", __func__);
10966 return;
10967 }
10968
10969 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
10970 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
10971 goto nla_put_failure;
10972
10973 pr_info("****FTM Rx cmd len = %zu*****\n", buf_len);
10974
10975 cfg80211_testmode_event(skb, GFP_KERNEL);
10976 return;
10977
10978nla_put_failure:
10979 kfree_skb(skb);
Anurag Chouhan6d760662016-02-20 16:05:43 +053010980 CDF_TRACE(QDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010981 "%s: nla_put failed on testmode rx skb!", __func__);
10982}
10983#endif
10984#endif /* CONFIG_NL80211_TESTMODE */
10985
10986#ifdef QCA_HT_2040_COEX
10987/**
10988 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
10989 * @wiphy: Pointer to wiphy
10990 * @dev: Pointer to network device
10991 * @chandef: Pointer to channel definition parameter
10992 *
10993 * Return: 0 for success, non-zero for failure
10994 */
10995static int
10996__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
10997 struct net_device *dev,
10998 struct cfg80211_chan_def *chandef)
10999{
11000 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11001 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011002 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011003 tSmeConfigParams sme_config;
11004 bool cbModeChange;
11005
Anurag Chouhan6d760662016-02-20 16:05:43 +053011006 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11008 return -EINVAL;
11009 }
11010
11011 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11012 status = wlan_hdd_validate_context(pHddCtx);
11013
11014 if (0 != status) {
11015 hddLog(LOGE, FL("HDD context is not valid"));
11016 return status;
11017 }
11018
11019 cdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
11020 sme_get_config_param(pHddCtx->hHal, &sme_config);
11021 switch (chandef->width) {
11022 case NL80211_CHAN_WIDTH_20:
11023 if (sme_config.csrConfig.channelBondingMode24GHz !=
11024 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11025 sme_config.csrConfig.channelBondingMode24GHz =
11026 eCSR_INI_SINGLE_CHANNEL_CENTERED;
11027 sme_update_config(pHddCtx->hHal, &sme_config);
11028 cbModeChange = true;
11029 }
11030 break;
11031
11032 case NL80211_CHAN_WIDTH_40:
11033 if (sme_config.csrConfig.channelBondingMode24GHz ==
11034 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11035 if (NL80211_CHAN_HT40MINUS ==
11036 cfg80211_get_chandef_type(chandef))
11037 sme_config.csrConfig.channelBondingMode24GHz =
11038 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
11039 else
11040 sme_config.csrConfig.channelBondingMode24GHz =
11041 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
11042 sme_update_config(pHddCtx->hHal, &sme_config);
11043 cbModeChange = true;
11044 }
11045 break;
11046
11047 default:
11048 hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !"));
11049 return -EINVAL;
11050 }
11051
11052 if (!cbModeChange)
11053 return 0;
11054
11055 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
11056 return 0;
11057
11058 hddLog(LOG1, FL("Channel bonding changed to %d"),
11059 sme_config.csrConfig.channelBondingMode24GHz);
11060
11061 /* Change SAP ht2040 mode */
11062 status = hdd_set_sap_ht2040_mode(pAdapter,
11063 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011064 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 hddLog(LOGE, FL("Error!!! Cannot set SAP HT20/40 mode!"));
11066 return -EINVAL;
11067 }
11068
11069 return 0;
11070}
11071
11072/**
11073 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11074 * @wiphy: Pointer to wiphy
11075 * @dev: Pointer to network device
11076 * @chandef: Pointer to channel definition parameter
11077 *
11078 * Return: 0 for success, non-zero for failure
11079 */
11080static int
11081wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11082 struct net_device *dev,
11083 struct cfg80211_chan_def *chandef)
11084{
11085 int ret;
11086
11087 cds_ssr_protect(__func__);
11088 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
11089 cds_ssr_unprotect(__func__);
11090
11091 return ret;
11092}
11093#endif
11094
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011095#ifdef CHANNEL_SWITCH_SUPPORTED
11096/**
11097 * __wlan_hdd_cfg80211_channel_switch()- function to switch
11098 * channel in SAP/GO
11099 * @wiphy: wiphy pointer
11100 * @dev: dev pointer.
11101 * @csa_params: Change channel params
11102 *
11103 * This function is called to switch channel in SAP/GO
11104 *
11105 * Return: 0 if success else return non zero
11106 */
11107static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11108 struct net_device *dev,
11109 struct cfg80211_csa_settings *csa_params)
11110{
11111 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
11112 hdd_context_t *hdd_ctx;
11113 uint8_t channel;
11114 uint16_t freq;
11115 int ret;
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053011116 phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011117
11118 hddLog(LOG1, FL("Set Freq %d"),
11119 csa_params->chandef.chan->center_freq);
11120
11121 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11122 ret = wlan_hdd_validate_context(hdd_ctx);
11123
11124 if (0 != ret)
11125 return ret;
11126
11127 if ((WLAN_HDD_P2P_GO != adapter->device_mode) &&
11128 (WLAN_HDD_SOFTAP != adapter->device_mode))
11129 return -ENOTSUPP;
11130
11131 freq = csa_params->chandef.chan->center_freq;
11132 channel = cds_freq_to_chan(freq);
11133
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053011134 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
11135
11136 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011137 return ret;
11138}
11139
11140/**
11141 * wlan_hdd_cfg80211_channel_switch()- function to switch
11142 * channel in SAP/GO
11143 * @wiphy: wiphy pointer
11144 * @dev: dev pointer.
11145 * @csa_params: Change channel params
11146 *
11147 * This function is called to switch channel in SAP/GO
11148 *
11149 * Return: 0 if success else return non zero
11150 */
11151static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11152 struct net_device *dev,
11153 struct cfg80211_csa_settings *csa_params)
11154{
11155 int ret;
11156
11157 cds_ssr_protect(__func__);
11158 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
11159 cds_ssr_unprotect(__func__);
11160 return ret;
11161}
11162#endif
11163
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011164/**
11165 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
11166 * translation from NL to policy manager type
11167 * @type: Generic connection mode type defined in NL
11168 *
11169 *
11170 * This function provides the type translation
11171 *
11172 * Return: cds_con_mode enum
11173 */
11174enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
11175 enum nl80211_iftype type)
11176{
11177 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
11178 switch (type) {
11179 case NL80211_IFTYPE_STATION:
11180 mode = CDS_STA_MODE;
11181 break;
11182 case NL80211_IFTYPE_P2P_CLIENT:
11183 mode = CDS_P2P_CLIENT_MODE;
11184 break;
11185 case NL80211_IFTYPE_P2P_GO:
11186 mode = CDS_P2P_GO_MODE;
11187 break;
11188 case NL80211_IFTYPE_AP:
11189 mode = CDS_SAP_MODE;
11190 break;
11191 case NL80211_IFTYPE_ADHOC:
11192 mode = CDS_IBSS_MODE;
11193 break;
11194 default:
11195 hddLog(LOGE, FL("Unsupported interface type (%d)"),
11196 type);
11197 }
11198 return mode;
11199}
11200
11201/**
11202 * struct cfg80211_ops - cfg80211_ops
11203 *
11204 * @add_virtual_intf: Add virtual interface
11205 * @del_virtual_intf: Delete virtual interface
11206 * @change_virtual_intf: Change virtual interface
11207 * @change_station: Change station
11208 * @add_beacon: Add beacon in sap mode
11209 * @del_beacon: Delete beacon in sap mode
11210 * @set_beacon: Set beacon in sap mode
11211 * @start_ap: Start ap
11212 * @change_beacon: Change beacon
11213 * @stop_ap: Stop ap
11214 * @change_bss: Change bss
11215 * @add_key: Add key
11216 * @get_key: Get key
11217 * @del_key: Delete key
11218 * @set_default_key: Set default key
11219 * @set_channel: Set channel
11220 * @scan: Scan
11221 * @connect: Connect
11222 * @disconnect: Disconnect
11223 * @join_ibss = Join ibss
11224 * @leave_ibss = Leave ibss
11225 * @set_wiphy_params = Set wiphy params
11226 * @set_tx_power = Set tx power
11227 * @get_tx_power = get tx power
11228 * @remain_on_channel = Remain on channel
11229 * @cancel_remain_on_channel = Cancel remain on channel
11230 * @mgmt_tx = Tx management frame
11231 * @mgmt_tx_cancel_wait = Cancel management tx wait
11232 * @set_default_mgmt_key = Set default management key
11233 * @set_txq_params = Set tx queue parameters
11234 * @get_station = Get station
11235 * @set_power_mgmt = Set power management
11236 * @del_station = Delete station
11237 * @add_station = Add station
11238 * @set_pmksa = Set pmksa
11239 * @del_pmksa = Delete pmksa
11240 * @flush_pmksa = Flush pmksa
11241 * @update_ft_ies = Update FT IEs
11242 * @tdls_mgmt = Tdls management
11243 * @tdls_oper = Tdls operation
11244 * @set_rekey_data = Set rekey data
11245 * @sched_scan_start = Scheduled scan start
11246 * @sched_scan_stop = Scheduled scan stop
11247 * @resume = Resume wlan
11248 * @suspend = Suspend wlan
11249 * @set_mac_acl = Set mac acl
11250 * @testmode_cmd = Test mode command
11251 * @set_ap_chanwidth = Set AP channel bandwidth
11252 * @dump_survey = Dump survey
11253 * @key_mgmt_set_pmk = Set pmk key management
11254 */
11255static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
11256 .add_virtual_intf = wlan_hdd_add_virtual_intf,
11257 .del_virtual_intf = wlan_hdd_del_virtual_intf,
11258 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
11259 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 .start_ap = wlan_hdd_cfg80211_start_ap,
11261 .change_beacon = wlan_hdd_cfg80211_change_beacon,
11262 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263 .change_bss = wlan_hdd_cfg80211_change_bss,
11264 .add_key = wlan_hdd_cfg80211_add_key,
11265 .get_key = wlan_hdd_cfg80211_get_key,
11266 .del_key = wlan_hdd_cfg80211_del_key,
11267 .set_default_key = wlan_hdd_cfg80211_set_default_key,
11268 .scan = wlan_hdd_cfg80211_scan,
11269 .connect = wlan_hdd_cfg80211_connect,
11270 .disconnect = wlan_hdd_cfg80211_disconnect,
11271 .join_ibss = wlan_hdd_cfg80211_join_ibss,
11272 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
11273 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
11274 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
11275 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
11276 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
11277 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
11278 .mgmt_tx = wlan_hdd_mgmt_tx,
11279 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
11280 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
11281 .set_txq_params = wlan_hdd_set_txq_params,
11282 .get_station = wlan_hdd_cfg80211_get_station,
11283 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
11284 .del_station = wlan_hdd_cfg80211_del_station,
11285 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011286 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
11287 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
11288 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080011289#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
11291#endif
11292#ifdef FEATURE_WLAN_TDLS
11293 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
11294 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
11295#endif
11296#ifdef WLAN_FEATURE_GTK_OFFLOAD
11297 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
11298#endif /* WLAN_FEATURE_GTK_OFFLOAD */
11299#ifdef FEATURE_WLAN_SCAN_PNO
11300 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
11301 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
11302#endif /*FEATURE_WLAN_SCAN_PNO */
11303 .resume = wlan_hdd_cfg80211_resume_wlan,
11304 .suspend = wlan_hdd_cfg80211_suspend_wlan,
11305 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
11306#ifdef WLAN_NL80211_TESTMODE
11307 .testmode_cmd = wlan_hdd_cfg80211_testmode,
11308#endif
11309#ifdef QCA_HT_2040_COEX
11310 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
11311#endif
11312 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011313#ifdef CHANNEL_SWITCH_SUPPORTED
11314 .channel_switch = wlan_hdd_cfg80211_channel_switch,
11315#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011316};