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