blob: b9624883fdce8c120faa262b1ab3851dae0b4650 [file] [log] [blame]
chrmhoffmannbb97ca42017-05-13 21:27:44 +02001/*
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
30
31
32/**========================================================================
33
34 \file wlan_hdd_cfg80211.c
35
36 \brief WLAN Host Device Driver implementation
37
38 ========================================================================*/
39
40/**=========================================================================
41
42 EDIT HISTORY FOR FILE
43
44
45 This section contains comments describing changes made to the module.
46 Notice that changes are listed in reverse chronological order.
47
48
49 $Header:$ $DateTime: $ $Author: $
50
51
52 when who what, where, why
53 -------- --- --------------------------------------------------------
54 21/12/09 Ashwani Created module.
55
56 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
57 Ganesh K
58 ==========================================================================*/
59
60
61#include <linux/version.h>
62#include <linux/module.h>
63#include <linux/kernel.h>
64#include <linux/init.h>
65#include <linux/wireless.h>
66#include <wlan_hdd_includes.h>
67#include <net/arp.h>
68#include <net/cfg80211.h>
69#include <linux/wireless.h>
70#include <wlan_hdd_wowl.h>
71#include <aniGlobal.h>
72#include "ccmApi.h"
73#include "sirParams.h"
74#include "dot11f.h"
75#include "wlan_hdd_assoc.h"
76#include "wlan_hdd_wext.h"
77#include "sme_Api.h"
78#include "wlan_hdd_p2p.h"
79#include "wlan_hdd_cfg80211.h"
80#include "wlan_hdd_hostapd.h"
81#include "sapInternal.h"
82#include "wlan_hdd_softap_tx_rx.h"
83#include "wlan_hdd_main.h"
84#include "wlan_hdd_assoc.h"
85#include "wlan_hdd_power.h"
86#include "wlan_hdd_trace.h"
87#include "vos_types.h"
88#include "vos_trace.h"
89#ifdef WLAN_BTAMP_FEATURE
90#include "bap_hdd_misc.h"
91#endif
92#include <qc_sap_ioctl.h>
93#include "wlan_hdd_tdls.h"
94#include "wlan_hdd_wmm.h"
95#include "wlan_qct_wda.h"
96#include "wlan_nv.h"
97#include "wlan_hdd_dev_pwr.h"
98
99#define g_mode_rates_size (12)
100#define a_mode_rates_size (8)
101#define FREQ_BASE_80211G (2407)
102#define FREQ_BAND_DIFF_80211G (5)
103#define MAX_SCAN_SSID 9
104#define MAX_PENDING_LOG 5
105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
106 ((uintptr_t)OFFSET_OF( tSirBssDescription, ieFields)))
107
108#define HDD2GHZCHAN(freq, chan, flag) { \
109 .band = IEEE80211_BAND_2GHZ, \
110 .center_freq = (freq), \
111 .hw_value = (chan),\
112 .flags = (flag), \
113 .max_antenna_gain = 0 ,\
114 .max_power = 30, \
115}
116
117#define HDD5GHZCHAN(freq, chan, flag) { \
118 .band = IEEE80211_BAND_5GHZ, \
119 .center_freq = (freq), \
120 .hw_value = (chan),\
121 .flags = (flag), \
122 .max_antenna_gain = 0 ,\
123 .max_power = 30, \
124}
125
126#define HDD_G_MODE_RATETAB(rate, rate_id, flag)\
127{\
128 .bitrate = rate, \
129 .hw_value = rate_id, \
130 .flags = flag, \
131}
132
133#ifdef WLAN_FEATURE_VOWIFI_11R
134#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
135#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
136#endif
137
138#define HDD_CHANNEL_14 14
139#define WLAN_HDD_MAX_FEATURE_SET 8
140
141#ifdef WLAN_FEATURE_LINK_LAYER_STATS
142/*
143 * Used to allocate the size of 4096 for the link layer stats.
144 * The size of 4096 is considered assuming that all data per
145 * respective event fit with in the limit.Please take a call
146 * on the limit based on the data requirements on link layer
147 * statistics.
148 */
149#define LL_STATS_EVENT_BUF_SIZE 4096
150#endif
151#ifdef WLAN_FEATURE_EXTSCAN
152/*
153 * Used to allocate the size of 4096 for the EXTScan NL data.
154 * The size of 4096 is considered assuming that all data per
155 * respective event fit with in the limit.Please take a call
156 * on the limit based on the data requirements.
157 */
158
159#define EXTSCAN_EVENT_BUF_SIZE 4096
160#define EXTSCAN_MAX_CACHED_RESULTS_PER_IND 32
161#endif
162
163/*EXT TDLS*/
164/*
165 * Used to allocate the size of 4096 for the TDLS.
166 * The size of 4096 is considered assuming that all data per
167 * respective event fit with in the limit.Please take a call
168 * on the limit based on the data requirements on link layer
169 * statistics.
170 */
171#define EXTTDLS_EVENT_BUF_SIZE 4096
172
173/*
174 * Values for Mac spoofing feature
175 *
176 */
177#define MAC_ADDR_SPOOFING_FW_HOST_DISABLE 0
178#define MAC_ADDR_SPOOFING_FW_HOST_ENABLE 1
179#define MAC_ADDR_SPOOFING_FW_ENABLE_HOST_DISABLE 2
180
181static const u32 hdd_cipher_suites[] =
182{
183 WLAN_CIPHER_SUITE_WEP40,
184 WLAN_CIPHER_SUITE_WEP104,
185 WLAN_CIPHER_SUITE_TKIP,
186#ifdef FEATURE_WLAN_ESE
187#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
188 WLAN_CIPHER_SUITE_KRK,
189 WLAN_CIPHER_SUITE_CCMP,
190#else
191 WLAN_CIPHER_SUITE_CCMP,
192#endif
193#ifdef FEATURE_WLAN_WAPI
194 WLAN_CIPHER_SUITE_SMS4,
195#endif
196#ifdef WLAN_FEATURE_11W
197 WLAN_CIPHER_SUITE_AES_CMAC,
198#endif
199};
200
201static inline int is_broadcast_ether_addr(const u8 *addr)
202{
203 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
204 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
205}
206
207const static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
208{
209 HDD2GHZCHAN(2412, 1, 0) ,
210 HDD2GHZCHAN(2417, 2, 0) ,
211 HDD2GHZCHAN(2422, 3, 0) ,
212 HDD2GHZCHAN(2427, 4, 0) ,
213 HDD2GHZCHAN(2432, 5, 0) ,
214 HDD2GHZCHAN(2437, 6, 0) ,
215 HDD2GHZCHAN(2442, 7, 0) ,
216 HDD2GHZCHAN(2447, 8, 0) ,
217 HDD2GHZCHAN(2452, 9, 0) ,
218 HDD2GHZCHAN(2457, 10, 0) ,
219 HDD2GHZCHAN(2462, 11, 0) ,
220 HDD2GHZCHAN(2467, 12, 0) ,
221 HDD2GHZCHAN(2472, 13, 0) ,
222 HDD2GHZCHAN(2484, 14, 0) ,
223};
224
225static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
226{
227 HDD2GHZCHAN(2412, 1, 0) ,
228 HDD2GHZCHAN(2437, 6, 0) ,
229 HDD2GHZCHAN(2462, 11, 0) ,
230};
231
232const static struct ieee80211_channel hdd_channels_5_GHZ[] =
233{
234 HDD5GHZCHAN(4920, 240, 0) ,
235 HDD5GHZCHAN(4940, 244, 0) ,
236 HDD5GHZCHAN(4960, 248, 0) ,
237 HDD5GHZCHAN(4980, 252, 0) ,
238 HDD5GHZCHAN(5040, 208, 0) ,
239 HDD5GHZCHAN(5060, 212, 0) ,
240 HDD5GHZCHAN(5080, 216, 0) ,
241 HDD5GHZCHAN(5180, 36, 0) ,
242 HDD5GHZCHAN(5200, 40, 0) ,
243 HDD5GHZCHAN(5220, 44, 0) ,
244 HDD5GHZCHAN(5240, 48, 0) ,
245 HDD5GHZCHAN(5260, 52, 0) ,
246 HDD5GHZCHAN(5280, 56, 0) ,
247 HDD5GHZCHAN(5300, 60, 0) ,
248 HDD5GHZCHAN(5320, 64, 0) ,
249 HDD5GHZCHAN(5500,100, 0) ,
250 HDD5GHZCHAN(5520,104, 0) ,
251 HDD5GHZCHAN(5540,108, 0) ,
252 HDD5GHZCHAN(5560,112, 0) ,
253 HDD5GHZCHAN(5580,116, 0) ,
254 HDD5GHZCHAN(5600,120, 0) ,
255 HDD5GHZCHAN(5620,124, 0) ,
256 HDD5GHZCHAN(5640,128, 0) ,
257 HDD5GHZCHAN(5660,132, 0) ,
258 HDD5GHZCHAN(5680,136, 0) ,
259 HDD5GHZCHAN(5700,140, 0) ,
260#ifdef FEATURE_WLAN_CH144
261 HDD5GHZCHAN(5720,144, 0) ,
262#endif /* FEATURE_WLAN_CH144 */
263 HDD5GHZCHAN(5745,149, 0) ,
264 HDD5GHZCHAN(5765,153, 0) ,
265 HDD5GHZCHAN(5785,157, 0) ,
266 HDD5GHZCHAN(5805,161, 0) ,
267 HDD5GHZCHAN(5825,165, 0) ,
268};
269
270static struct ieee80211_rate g_mode_rates[] =
271{
272 HDD_G_MODE_RATETAB(10, 0x1, 0),
273 HDD_G_MODE_RATETAB(20, 0x2, 0),
274 HDD_G_MODE_RATETAB(55, 0x4, 0),
275 HDD_G_MODE_RATETAB(110, 0x8, 0),
276 HDD_G_MODE_RATETAB(60, 0x10, 0),
277 HDD_G_MODE_RATETAB(90, 0x20, 0),
278 HDD_G_MODE_RATETAB(120, 0x40, 0),
279 HDD_G_MODE_RATETAB(180, 0x80, 0),
280 HDD_G_MODE_RATETAB(240, 0x100, 0),
281 HDD_G_MODE_RATETAB(360, 0x200, 0),
282 HDD_G_MODE_RATETAB(480, 0x400, 0),
283 HDD_G_MODE_RATETAB(540, 0x800, 0),
284};
285
286static struct ieee80211_rate a_mode_rates[] =
287{
288 HDD_G_MODE_RATETAB(60, 0x10, 0),
289 HDD_G_MODE_RATETAB(90, 0x20, 0),
290 HDD_G_MODE_RATETAB(120, 0x40, 0),
291 HDD_G_MODE_RATETAB(180, 0x80, 0),
292 HDD_G_MODE_RATETAB(240, 0x100, 0),
293 HDD_G_MODE_RATETAB(360, 0x200, 0),
294 HDD_G_MODE_RATETAB(480, 0x400, 0),
295 HDD_G_MODE_RATETAB(540, 0x800, 0),
296};
297
298static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
299{
300 .channels = NULL,
301 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
302 .band = IEEE80211_BAND_2GHZ,
303 .bitrates = g_mode_rates,
304 .n_bitrates = g_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 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
311 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
312 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
313 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
314 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
315};
316
317static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
318{
319 .channels = hdd_social_channels_2_4_GHZ,
320 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
321 .band = IEEE80211_BAND_2GHZ,
322 .bitrates = g_mode_rates,
323 .n_bitrates = g_mode_rates_size,
324 .ht_cap.ht_supported = 1,
325 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
326 | IEEE80211_HT_CAP_GRN_FLD
327 | IEEE80211_HT_CAP_DSSSCCK40
328 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
329 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
330 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
331 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
332 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
333 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
334};
335
336static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
337{
338 .channels = NULL,
339 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
340 .band = IEEE80211_BAND_5GHZ,
341 .bitrates = a_mode_rates,
342 .n_bitrates = a_mode_rates_size,
343 .ht_cap.ht_supported = 1,
344 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
345 | IEEE80211_HT_CAP_GRN_FLD
346 | IEEE80211_HT_CAP_DSSSCCK40
347 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
348 | IEEE80211_HT_CAP_SGI_40
349 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
350 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
351 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
352 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
353 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
354 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
355};
356
357/* This structure contain information what kind of frame are expected in
358 TX/RX direction for each kind of interface */
359static const struct ieee80211_txrx_stypes
360wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
361 [NL80211_IFTYPE_STATION] = {
362 .tx = 0xffff,
363 .rx = BIT(SIR_MAC_MGMT_ACTION) |
364 BIT(SIR_MAC_MGMT_PROBE_REQ),
365 },
366 [NL80211_IFTYPE_AP] = {
367 .tx = 0xffff,
368 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
369 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
370 BIT(SIR_MAC_MGMT_PROBE_REQ) |
371 BIT(SIR_MAC_MGMT_DISASSOC) |
372 BIT(SIR_MAC_MGMT_AUTH) |
373 BIT(SIR_MAC_MGMT_DEAUTH) |
374 BIT(SIR_MAC_MGMT_ACTION),
375 },
376 [NL80211_IFTYPE_ADHOC] = {
377 .tx = 0xffff,
378 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
379 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
380 BIT(SIR_MAC_MGMT_PROBE_REQ) |
381 BIT(SIR_MAC_MGMT_DISASSOC) |
382 BIT(SIR_MAC_MGMT_AUTH) |
383 BIT(SIR_MAC_MGMT_DEAUTH) |
384 BIT(SIR_MAC_MGMT_ACTION),
385 },
386 [NL80211_IFTYPE_P2P_CLIENT] = {
387 .tx = 0xffff,
388 .rx = BIT(SIR_MAC_MGMT_ACTION) |
389 BIT(SIR_MAC_MGMT_PROBE_REQ),
390 },
391 [NL80211_IFTYPE_P2P_GO] = {
392 /* This is also same as for SoftAP */
393 .tx = 0xffff,
394 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
395 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
396 BIT(SIR_MAC_MGMT_PROBE_REQ) |
397 BIT(SIR_MAC_MGMT_DISASSOC) |
398 BIT(SIR_MAC_MGMT_AUTH) |
399 BIT(SIR_MAC_MGMT_DEAUTH) |
400 BIT(SIR_MAC_MGMT_ACTION),
401 },
402};
403
404#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
405static const struct ieee80211_iface_limit
406wlan_hdd_iface_limit[] = {
407 {
408 /* max = 3 ; Our driver create two interfaces during driver init
409 * wlan0 and p2p0 interfaces. p2p0 is considered as station
410 * interface until a group is formed. In JB architecture, once the
411 * group is formed, interface type of p2p0 is changed to P2P GO or
412 * Client.
413 * When supplicant remove the group, it first issue a set interface
414 * cmd to change the mode back to Station. In JB this works fine as
415 * we advertize two station type interface during driver init.
416 * Some vendors create separate interface for P2P GO/Client,
417 * after group formation(Third one). But while group remove
418 * supplicant first tries to change the mode(3rd interface) to STATION
419 * But as we advertized only two sta type interfaces nl80211 was
420 * returning error for the third one which was leading to failure in
421 * delete interface. Ideally while removing the group, supplicant
422 * should not try to change the 3rd interface mode to Station type.
423 * Till we get a fix in wpa_supplicant, we advertize max STA
424 * interface type to 3
425 */
426 .max = 3,
427 .types = BIT(NL80211_IFTYPE_STATION),
428 },
429 {
430 .max = 1,
431 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
432 },
433 {
434 .max = 1,
435 .types = BIT(NL80211_IFTYPE_P2P_GO) |
436 BIT(NL80211_IFTYPE_P2P_CLIENT),
437 },
438};
439
440/* By default, only single channel concurrency is allowed */
441static struct ieee80211_iface_combination
442wlan_hdd_iface_combination = {
443 .limits = wlan_hdd_iface_limit,
444 .num_different_channels = 1,
445 /*
446 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
447 * and p2p0 interfaces during driver init
448 * Some vendors create separate interface for P2P operations.
449 * wlan0: STA interface
450 * p2p0: P2P Device interface, action frames goes
451 * through this interface.
452 * p2p-xx: P2P interface, After GO negotiation this interface is
453 * created for p2p operations(GO/CLIENT interface).
454 */
455 .max_interfaces = WLAN_MAX_INTERFACES,
456 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
457 .beacon_int_infra_match = false,
458};
459#endif
460
461static struct cfg80211_ops wlan_hdd_cfg80211_ops;
462
463/* Data rate 100KBPS based on IE Index */
464struct index_data_rate_type
465{
466 v_U8_t beacon_rate_index;
467 v_U16_t supported_rate[4];
468};
469
470/* 11B, 11G Rate table include Basic rate and Extended rate
471 The IDX field is the rate index
472 The HI field is the rate when RSSI is strong or being ignored
473 (in this case we report actual rate)
474 The MID field is the rate when RSSI is moderate
475 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
476 The LO field is the rate when RSSI is low
477 (in this case we don't report rates, actual current rate used)
478 */
479static const struct
480{
481 v_U8_t beacon_rate_index;
482 v_U16_t supported_rate[4];
483} supported_data_rate[] =
484{
485/* IDX HI HM LM LO (RSSI-based index */
486 {2, { 10, 10, 10, 0}},
487 {4, { 20, 20, 10, 0}},
488 {11, { 55, 20, 10, 0}},
489 {12, { 60, 55, 20, 0}},
490 {18, { 90, 55, 20, 0}},
491 {22, {110, 55, 20, 0}},
492 {24, {120, 90, 60, 0}},
493 {36, {180, 120, 60, 0}},
494 {44, {220, 180, 60, 0}},
495 {48, {240, 180, 90, 0}},
496 {66, {330, 180, 90, 0}},
497 {72, {360, 240, 90, 0}},
498 {96, {480, 240, 120, 0}},
499 {108, {540, 240, 120, 0}}
500};
501
502/* MCS Based rate table */
503static struct index_data_rate_type supported_mcs_rate[] =
504{
505/* MCS L20 L40 S20 S40 */
506 {0, {65, 135, 72, 150}},
507 {1, {130, 270, 144, 300}},
508 {2, {195, 405, 217, 450}},
509 {3, {260, 540, 289, 600}},
510 {4, {390, 810, 433, 900}},
511 {5, {520, 1080, 578, 1200}},
512 {6, {585, 1215, 650, 1350}},
513 {7, {650, 1350, 722, 1500}}
514};
515
516#ifdef WLAN_FEATURE_11AC
517
518#define DATA_RATE_11AC_MCS_MASK 0x03
519
520struct index_vht_data_rate_type
521{
522 v_U8_t beacon_rate_index;
523 v_U16_t supported_VHT80_rate[2];
524 v_U16_t supported_VHT40_rate[2];
525 v_U16_t supported_VHT20_rate[2];
526};
527
528typedef enum
529{
530 DATA_RATE_11AC_MAX_MCS_7,
531 DATA_RATE_11AC_MAX_MCS_8,
532 DATA_RATE_11AC_MAX_MCS_9,
533 DATA_RATE_11AC_MAX_MCS_NA
534} eDataRate11ACMaxMcs;
535
536/* SSID broadcast type */
537typedef enum eSSIDBcastType
538{
539 eBCAST_UNKNOWN = 0,
540 eBCAST_NORMAL = 1,
541 eBCAST_HIDDEN = 2,
542} tSSIDBcastType;
543
544/* MCS Based VHT rate table */
545static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
546{
547/* MCS L80 S80 L40 S40 L20 S40*/
548 {0, {293, 325}, {135, 150}, {65, 72}},
549 {1, {585, 650}, {270, 300}, {130, 144}},
550 {2, {878, 975}, {405, 450}, {195, 217}},
551 {3, {1170, 1300}, {540, 600}, {260, 289}},
552 {4, {1755, 1950}, {810, 900}, {390, 433}},
553 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
554 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
555 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
556 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
557 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
558};
559#endif /* WLAN_FEATURE_11AC */
560
561/*array index points to MCS and array value points respective rssi*/
562static int rssiMcsTbl[][10] =
563{
564/*MCS 0 1 2 3 4 5 6 7 8 9*/
565 {-82, -79, -77, -74, -70, -66, -65, -64, -59, -57}, //20
566 {-79, -76, -74, -71, -67, -63, -62, -61, -56, -54}, //40
567 {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} //80
568};
569
570extern struct net_device_ops net_ops_struct;
571#ifdef FEATURE_WLAN_SCAN_PNO
572static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter);
573#endif
574
575#ifdef WLAN_NL80211_TESTMODE
576enum wlan_hdd_tm_attr
577{
578 WLAN_HDD_TM_ATTR_INVALID = 0,
579 WLAN_HDD_TM_ATTR_CMD = 1,
580 WLAN_HDD_TM_ATTR_DATA = 2,
581 WLAN_HDD_TM_ATTR_TYPE = 3,
582 /* keep last */
583 WLAN_HDD_TM_ATTR_AFTER_LAST,
584 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
585};
586
587enum wlan_hdd_tm_cmd
588{
589 WLAN_HDD_TM_CMD_WLAN_HB = 1,
590};
591
592#define WLAN_HDD_TM_DATA_MAX_LEN 5000
593
594static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
595{
596 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
597 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
598 .len = WLAN_HDD_TM_DATA_MAX_LEN },
599};
600#endif /* WLAN_NL80211_TESTMODE */
601
602#ifdef FEATURE_WLAN_CH_AVOID
603/*
604 * FUNCTION: wlan_hdd_send_avoid_freq_event
605 * This is called when wlan driver needs to send vendor specific
606 * avoid frequency range event to userspace
607 */
608int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
609 tHddAvoidFreqList *pAvoidFreqList)
610{
611 struct sk_buff *vendor_event;
612
613 ENTER();
614
615 if (!pHddCtx)
616 {
617 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
618 "%s: HDD context is null", __func__);
619 return -1;
620 }
621
622 if (!pAvoidFreqList)
623 {
624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
625 "%s: pAvoidFreqList is null", __func__);
626 return -1;
627 }
628
629 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
630#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
631 NULL,
632#endif
633 sizeof(tHddAvoidFreqList),
634 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
635 GFP_KERNEL);
636 if (!vendor_event)
637 {
638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
639 "%s: cfg80211_vendor_event_alloc failed", __func__);
640 return -1;
641 }
642
643 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
644 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
645
646 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
647
648 EXIT();
649 return 0;
650}
651#endif /* FEATURE_WLAN_CH_AVOID */
652
653/*
654 * FUNCTION: __wlan_hdd_cfg80211_nan_request
655 * This is called when wlan driver needs to send vendor specific
656 * nan request event.
657 */
658static int __wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy,
659 struct wireless_dev *wdev,
660 const void *data, int data_len)
661{
662 tNanRequestReq nan_req;
663 VOS_STATUS status;
664 int ret_val = -1;
665 struct net_device *dev = wdev->netdev;
666 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
667 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
668 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
669
670 if (0 == data_len)
671 {
672 hddLog(VOS_TRACE_LEVEL_ERROR,
673 FL("NAN - Invalid Request, length = 0"));
674 return ret_val;
675 }
676
677 if (NULL == data)
678 {
679 hddLog(VOS_TRACE_LEVEL_ERROR,
680 FL("NAN - Invalid Request, data is NULL"));
681 return ret_val;
682 }
683
684 status = wlan_hdd_validate_context(pHddCtx);
685 if (0 != status)
686 {
687 hddLog(VOS_TRACE_LEVEL_ERROR,
688 FL("HDD context is not valid"));
689 return -EINVAL;
690 }
691
692 hddLog(LOG1, FL("Received NAN command"));
693 vos_trace_hex_dump( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
694 (tANI_U8 *)data, data_len);
695
696 /* check the NAN Capability */
697 if (TRUE != sme_IsFeatureSupportedByFW(NAN))
698 {
699 hddLog(VOS_TRACE_LEVEL_ERROR,
700 FL("NAN is not supported by Firmware"));
701 return -EINVAL;
702 }
703
704 nan_req.request_data_len = data_len;
705 nan_req.request_data = data;
706
707 status = sme_NanRequest(hHal, &nan_req, pAdapter->sessionId);
708 if (VOS_STATUS_SUCCESS == status)
709 {
710 ret_val = 0;
711 }
712 return ret_val;
713}
714
715/*
716 * FUNCTION: wlan_hdd_cfg80211_nan_request
717 * Wrapper to protect the nan vendor command from ssr
718 */
719static int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy,
720 struct wireless_dev *wdev,
721 const void *data, int data_len)
722{
723 int ret;
724
725 vos_ssr_protect(__func__);
726 ret = __wlan_hdd_cfg80211_nan_request(wiphy, wdev, data, data_len);
727 vos_ssr_unprotect(__func__);
728
729 return ret;
730}
731
732/*
733 * FUNCTION: wlan_hdd_cfg80211_nan_callback
734 * This is a callback function and it gets called
735 * when we need to report nan response event to
736 * upper layers.
737 */
738static void wlan_hdd_cfg80211_nan_callback(void* ctx, tSirNanEvent* msg)
739{
740 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
741 struct sk_buff *vendor_event;
742 int status;
743 tSirNanEvent *data;
744
745 ENTER();
746 if (NULL == msg)
747 {
748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
749 FL(" msg received here is null"));
750 return;
751 }
752 data = msg;
753
754 status = wlan_hdd_validate_context(pHddCtx);
755
756 if (0 != status)
757 {
758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
759 FL("HDD context is not valid"));
760 return;
761 }
762
763 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
764#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
765 NULL,
766#endif
767 data->event_data_len +
768 NLMSG_HDRLEN,
769 QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX,
770 GFP_KERNEL);
771
772 if (!vendor_event)
773 {
774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
775 FL("cfg80211_vendor_event_alloc failed"));
776 return;
777 }
778 if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NAN,
779 data->event_data_len, data->event_data))
780 {
781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
782 FL("QCA_WLAN_VENDOR_ATTR_NAN put fail"));
783 kfree_skb(vendor_event);
784 return;
785 }
786 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
787 EXIT();
788}
789
790/*
791 * FUNCTION: wlan_hdd_cfg80211_nan_init
792 * This function is called to register the callback to sme layer
793 */
794inline void wlan_hdd_cfg80211_nan_init(hdd_context_t *pHddCtx)
795{
796 sme_NanRegisterCallback(pHddCtx->hHal, wlan_hdd_cfg80211_nan_callback);
797}
798
799
800#ifdef WLAN_FEATURE_LINK_LAYER_STATS
801
802static v_BOOL_t put_wifi_rate_stat( tpSirWifiRateStat stats,
803 struct sk_buff *vendor_event)
804{
805 if (nla_put_u8(vendor_event,
806 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE,
807 stats->rate.preamble) ||
808 nla_put_u8(vendor_event,
809 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS,
810 stats->rate.nss) ||
811 nla_put_u8(vendor_event,
812 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW,
813 stats->rate.bw) ||
814 nla_put_u8(vendor_event,
815 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX,
816 stats->rate.rateMcsIdx) ||
817 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE,
818 stats->rate.bitrate ) ||
819 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU,
820 stats->txMpdu ) ||
821 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU,
822 stats->rxMpdu ) ||
823 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST,
824 stats->mpduLost ) ||
825 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES,
826 stats->retries) ||
827 nla_put_u32(vendor_event,
828 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT,
829 stats->retriesShort ) ||
830 nla_put_u32(vendor_event,
831 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG,
832 stats->retriesLong))
833 {
834 hddLog(VOS_TRACE_LEVEL_ERROR,
835 FL("QCA_WLAN_VENDOR_ATTR put fail"));
836 return FALSE;
837 }
838 return TRUE;
839}
840
841static v_BOOL_t put_wifi_peer_info( tpSirWifiPeerInfo stats,
842 struct sk_buff *vendor_event)
843{
844 u32 i = 0;
845 struct nlattr *rateInfo;
846 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE,
847 stats->type) ||
848 nla_put(vendor_event,
849 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS,
850 VOS_MAC_ADDR_SIZE, &stats->peerMacAddress[0]) ||
851 nla_put_u32(vendor_event,
852 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES,
853 stats->capabilities) ||
854 nla_put_u32(vendor_event,
855 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES,
856 stats->numRate))
857 {
858 hddLog(VOS_TRACE_LEVEL_ERROR,
859 FL("QCA_WLAN_VENDOR_ATTR put fail"));
860 goto error;
861 }
862
863 rateInfo = nla_nest_start(vendor_event,
864 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO);
865 if(!rateInfo)
866 return FALSE;
867 for (i = 0; i < stats->numRate; i++)
868 {
869 struct nlattr *rates;
870 tpSirWifiRateStat pRateStats = (tpSirWifiRateStat )((uint8 *)
871 stats->rateStats +
872 (i * sizeof(tSirWifiRateStat)));
873 rates = nla_nest_start(vendor_event, i);
874 if(!rates)
875 return FALSE;
876
877 if (FALSE == put_wifi_rate_stat(pRateStats, vendor_event))
878 {
879 hddLog(VOS_TRACE_LEVEL_ERROR,
880 FL("QCA_WLAN_VENDOR_ATTR put fail"));
881 return FALSE;
882 }
883 nla_nest_end(vendor_event, rates);
884 }
885 nla_nest_end(vendor_event, rateInfo);
886
887 return TRUE;
888error:
889 return FALSE;
890}
891
892static v_BOOL_t put_wifi_wmm_ac_stat( tpSirWifiWmmAcStat stats,
893 struct sk_buff *vendor_event)
894{
895 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC,
896 stats->ac ) ||
897 nla_put_u32(vendor_event,
898 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU,
899 stats->txMpdu ) ||
900 nla_put_u32(vendor_event,
901 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU,
902 stats->rxMpdu ) ||
903 nla_put_u32(vendor_event,
904 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST,
905 stats->txMcast ) ||
906 nla_put_u32(vendor_event,
907 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST,
908 stats->rxMcast ) ||
909 nla_put_u32(vendor_event,
910 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU,
911 stats->rxAmpdu ) ||
912 nla_put_u32(vendor_event,
913 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU,
914 stats->txAmpdu ) ||
915 nla_put_u32(vendor_event,
916 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST,
917 stats->mpduLost )||
918 nla_put_u32(vendor_event,
919 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES,
920 stats->retries ) ||
921 nla_put_u32(vendor_event,
922 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT,
923 stats->retriesShort ) ||
924 nla_put_u32(vendor_event,
925 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG,
926 stats->retriesLong ) ||
927 nla_put_u32(vendor_event,
928 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN,
929 stats->contentionTimeMin ) ||
930 nla_put_u32(vendor_event,
931 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX,
932 stats->contentionTimeMax ) ||
933 nla_put_u32(vendor_event,
934 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG,
935 stats->contentionTimeAvg ) ||
936 nla_put_u32(vendor_event,
937 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES,
938 stats->contentionNumSamples ))
939 {
940 hddLog(VOS_TRACE_LEVEL_ERROR,
941 FL("QCA_WLAN_VENDOR_ATTR put fail") );
942 return FALSE;
943 }
944 return TRUE;
945}
946
947static v_BOOL_t put_wifi_interface_info(tpSirWifiInterfaceInfo stats,
948 struct sk_buff *vendor_event)
949{
950 if (nla_put_s32(vendor_event,
951 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE, stats->mode ) ||
952 nla_put(vendor_event,
953 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR,
954 VOS_MAC_ADDR_SIZE, stats->macAddr) ||
955 nla_put_u32(vendor_event,
956 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE,
957 stats->state ) ||
958 nla_put_u32(vendor_event,
959 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING,
960 stats->roaming ) ||
961 nla_put_u32(vendor_event,
962 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES,
963 stats->capabilities ) ||
964 nla_put(vendor_event,
965 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID,
966 strlen(stats->ssid), stats->ssid) ||
967 nla_put(vendor_event,
968 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID,
969 WNI_CFG_BSSID_LEN, stats->bssid) ||
970 nla_put(vendor_event,
971 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR,
972 WNI_CFG_COUNTRY_CODE_LEN, stats->apCountryStr) ||
973 nla_put(vendor_event,
974 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR,
975 WNI_CFG_COUNTRY_CODE_LEN, stats->countryStr)
976 )
977 {
978 hddLog(VOS_TRACE_LEVEL_ERROR,
979 FL("QCA_WLAN_VENDOR_ATTR put fail") );
980 return FALSE;
981 }
982 return TRUE;
983}
984
985static v_BOOL_t put_wifi_iface_stats(hdd_adapter_t *pAdapter,
986 tpSirWifiIfaceStat pWifiIfaceStat,
987 struct sk_buff *vendor_event)
988{
989 int i = 0;
990 struct nlattr *wmmInfo;
991 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
992 WLANTL_InterfaceStatsType *pWifiIfaceStatTL = NULL;
993 tSirWifiWmmAcStat accessclassStats;
994
995 if (FALSE == put_wifi_interface_info(
996 &pWifiIfaceStat->info,
997 vendor_event))
998 {
999 hddLog(VOS_TRACE_LEVEL_ERROR,
1000 FL("QCA_WLAN_VENDOR_ATTR put fail") );
1001 return FALSE;
1002
1003 }
1004 pWifiIfaceStatTL = (WLANTL_InterfaceStatsType *)
1005 vos_mem_malloc(sizeof(WLANTL_InterfaceStatsType));
1006 if (NULL == pWifiIfaceStatTL)
1007 {
1008 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
1009 return FALSE;
1010 }
1011
1012 accessclassStats = pWifiIfaceStat->AccessclassStats[WIFI_AC_BK];
1013 pWifiIfaceStat->AccessclassStats[WIFI_AC_BK] =
1014 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE];
1015 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE] = accessclassStats;
1016
1017 accessclassStats.ac = pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].ac;
1018 pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].ac =
1019 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].ac;
1020 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].ac = accessclassStats.ac;
1021
1022 if ( pWifiIfaceStat->info.state == WIFI_ASSOCIATED)
1023 {
1024 if (VOS_STATUS_SUCCESS ==
1025 WLANTL_CollectInterfaceStats((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
1026 pHddStaCtx->conn_info.staId[0], pWifiIfaceStatTL))
1027 {
1028 /* mgmtRx, MgmtActionRx, rxMcast, rxMpdu, rxAmpdu, rssiData are
1029 * obtained from TL structure
1030 */
1031
1032 pWifiIfaceStat->mgmtRx = pWifiIfaceStat->beaconRx +
1033 pWifiIfaceStatTL->mgmtRx;
1034 pWifiIfaceStat->rssiData = pWifiIfaceStatTL->rssiData;
1035
1036 pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].rxMcast
1037 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO].rxMcast;
1038 pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].rxMcast
1039 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI].rxMcast;
1040 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].rxMcast
1041 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE].rxMcast;
1042 pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].rxMcast
1043 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK].rxMcast;
1044
1045 pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].rxMpdu
1046 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO].rxMpdu;
1047 pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].rxMpdu
1048 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI].rxMpdu;
1049 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].rxMpdu
1050 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE].rxMpdu;
1051 pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].rxMpdu
1052 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK].rxMpdu;
1053
1054 pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].rxAmpdu
1055 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VO].rxAmpdu;
1056 pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].rxAmpdu
1057 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_VI].rxAmpdu;
1058 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].rxAmpdu
1059 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BE].rxAmpdu;
1060 pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].rxAmpdu
1061 = pWifiIfaceStatTL->accessCategoryStats[WLANTL_AC_BK].rxAmpdu;
1062 }
1063 else
1064 {
1065 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Error in getting stats from TL"));
1066 }
1067
1068 pWifiIfaceStat->AccessclassStats[WIFI_AC_VO].txMcast =
1069 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VO];
1070 pWifiIfaceStat->AccessclassStats[WIFI_AC_VI].txMcast =
1071 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VI];
1072 pWifiIfaceStat->AccessclassStats[WIFI_AC_BE].txMcast =
1073 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BE];
1074 pWifiIfaceStat->AccessclassStats[WIFI_AC_BK].txMcast =
1075 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BK];
1076 }
1077 else
1078 {
1079 hddLog(VOS_TRACE_LEVEL_INFO, FL("Interface not Associated"));
1080 }
1081
1082
1083
1084 if (nla_put_u32(vendor_event,
1085 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
1086 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_IFACE) ||
1087 nla_put_u32(vendor_event,
1088 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX,
1089 pWifiIfaceStat->beaconRx) ||
1090 nla_put_u32(vendor_event,
1091 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX,
1092 pWifiIfaceStat->mgmtRx) ||
1093 nla_put_u32(vendor_event,
1094 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX,
1095 pWifiIfaceStat->mgmtActionRx) ||
1096 nla_put_u32(vendor_event,
1097 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX,
1098 pWifiIfaceStat->mgmtActionTx) ||
1099 nla_put_s32(vendor_event,
1100 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT,
1101 pWifiIfaceStat->rssiMgmt) ||
1102 nla_put_s32(vendor_event,
1103 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA,
1104 pWifiIfaceStat->rssiData) ||
1105 nla_put_s32(vendor_event,
1106 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK,
1107 pWifiIfaceStat->rssiAck))
1108 {
1109 hddLog(VOS_TRACE_LEVEL_ERROR,
1110 FL("QCA_WLAN_VENDOR_ATTR put fail"));
1111 vos_mem_free(pWifiIfaceStatTL);
1112 return FALSE;
1113 }
1114
1115 wmmInfo = nla_nest_start(vendor_event,
1116 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO);
1117 if(!wmmInfo)
1118 {
1119 vos_mem_free(pWifiIfaceStatTL);
1120 return FALSE;
1121 }
1122 for (i = 0; i < WIFI_AC_MAX; i++)
1123 {
1124 struct nlattr *wmmStats;
1125 wmmStats = nla_nest_start(vendor_event, i);
1126 if(!wmmStats)
1127 {
1128 vos_mem_free(pWifiIfaceStatTL);
1129 return FALSE;
1130 }
1131 if (FALSE == put_wifi_wmm_ac_stat(
1132 &pWifiIfaceStat->AccessclassStats[i],
1133 vendor_event))
1134 {
1135 hddLog(VOS_TRACE_LEVEL_ERROR,
1136 FL("QCA_WLAN_VENDOR_ATTR put Fail"));
1137 vos_mem_free(pWifiIfaceStatTL);
1138 return FALSE;
1139 }
1140
1141 nla_nest_end(vendor_event, wmmStats);
1142 }
1143 nla_nest_end(vendor_event, wmmInfo);
1144 vos_mem_free(pWifiIfaceStatTL);
1145 return TRUE;
1146}
1147
1148static tSirWifiInterfaceMode
1149 hdd_map_device_to_ll_iface_mode ( int deviceMode )
1150{
1151 switch (deviceMode)
1152 {
1153 case WLAN_HDD_INFRA_STATION:
1154 return WIFI_INTERFACE_STA;
1155 case WLAN_HDD_SOFTAP:
1156 return WIFI_INTERFACE_SOFTAP;
1157 case WLAN_HDD_P2P_CLIENT:
1158 return WIFI_INTERFACE_P2P_CLIENT;
1159 case WLAN_HDD_P2P_GO:
1160 return WIFI_INTERFACE_P2P_GO;
1161 case WLAN_HDD_IBSS:
1162 return WIFI_INTERFACE_IBSS;
1163 default:
1164 return WIFI_INTERFACE_UNKNOWN;
1165 }
1166}
1167
1168static v_BOOL_t hdd_get_interface_info(hdd_adapter_t *pAdapter,
1169 tpSirWifiInterfaceInfo pInfo)
1170{
1171 v_U8_t *staMac = NULL;
1172 hdd_station_ctx_t *pHddStaCtx;
1173 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1174 tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
1175
1176 pInfo->mode = hdd_map_device_to_ll_iface_mode(pAdapter->device_mode);
1177
1178 vos_mem_copy(pInfo->macAddr,
1179 pAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1180
1181 if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
1182 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1183 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)))
1184 {
1185 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1186 if (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState)
1187 {
1188 pInfo->state = WIFI_DISCONNECTED;
1189 }
1190 if (eConnectionState_Connecting == pHddStaCtx->conn_info.connState)
1191 {
1192 hddLog(VOS_TRACE_LEVEL_ERROR,
1193 "%s: Session ID %d, Connection is in progress", __func__,
1194 pAdapter->sessionId);
1195 pInfo->state = WIFI_ASSOCIATING;
1196 }
1197 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
1198 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
1199 {
1200 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
1201 hddLog(VOS_TRACE_LEVEL_ERROR,
1202 "%s: client " MAC_ADDRESS_STR
1203 " is in the middle of WPS/EAPOL exchange.", __func__,
1204 MAC_ADDR_ARRAY(staMac));
1205 pInfo->state = WIFI_AUTHENTICATING;
1206 }
1207 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
1208 {
1209 pInfo->state = WIFI_ASSOCIATED;
1210 vos_mem_copy(pInfo->bssid,
1211 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN);
1212 vos_mem_copy(pInfo->ssid,
1213 pHddStaCtx->conn_info.SSID.SSID.ssId,
1214 pHddStaCtx->conn_info.SSID.SSID.length);
1215 //NULL Terminate the string.
1216 pInfo->ssid[pHddStaCtx->conn_info.SSID.SSID.length] = 0;
1217 }
1218 }
1219 vos_mem_copy(pInfo->countryStr,
1220 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
1221
1222 vos_mem_copy(pInfo->apCountryStr,
1223 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
1224
1225 return TRUE;
1226}
1227
1228/*
1229 * hdd_link_layer_process_peer_stats () - This function is called after
1230 * receiving Link Layer Peer statistics from FW.This function converts
1231 * the firmware data to the NL data and sends the same to the kernel/upper
1232 * layers.
1233 */
1234static v_VOID_t hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter,
1235 v_VOID_t *pData)
1236{
1237 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1238 tpSirWifiPeerStat pWifiPeerStat;
1239 tpSirWifiPeerInfo pWifiPeerInfo;
1240 struct nlattr *peerInfo;
1241 struct sk_buff *vendor_event;
1242 int status, i;
1243
1244 ENTER();
1245
1246 status = wlan_hdd_validate_context(pHddCtx);
1247 if (0 != status)
1248 {
1249 return;
1250 }
1251
1252 pWifiPeerStat = (tpSirWifiPeerStat) pData;
1253
1254 hddLog(VOS_TRACE_LEVEL_INFO,
1255 "LL_STATS_PEER_ALL : numPeers %u",
1256 pWifiPeerStat->numPeers);
1257 /*
1258 * Allocate a size of 4096 for the peer stats comprising
1259 * each of size = sizeof (tSirWifiPeerInfo) + numRate *
1260 * sizeof (tSirWifiRateStat).Each field is put with an
1261 * NL attribute.The size of 4096 is considered assuming
1262 * that number of rates shall not exceed beyond 50 with
1263 * the sizeof (tSirWifiRateStat) being 32.
1264 */
1265 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
1266 LL_STATS_EVENT_BUF_SIZE);
1267 if (!vendor_event)
1268 {
1269 hddLog(VOS_TRACE_LEVEL_ERROR,
1270 "%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
1271 __func__);
1272 return;
1273 }
1274 if (nla_put_u32(vendor_event,
1275 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
1276 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_PEER) ||
1277 nla_put_u32(vendor_event,
1278 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS,
1279 pWifiPeerStat->numPeers))
1280 {
1281 hddLog(VOS_TRACE_LEVEL_ERROR,
1282 "%s: QCA_WLAN_VENDOR_ATTR put fail", __func__);
1283 kfree_skb(vendor_event);
1284 return;
1285 }
1286
1287 peerInfo = nla_nest_start(vendor_event,
1288 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO);
1289 if(!peerInfo)
1290 {
1291 hddLog(VOS_TRACE_LEVEL_ERROR,
1292 "%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO put fail",
1293 __func__);
1294 kfree_skb(vendor_event);
1295 return;
1296 }
1297
1298 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8 *)
1299 pWifiPeerStat->peerInfo);
1300
1301 for (i = 1; i <= pWifiPeerStat->numPeers; i++)
1302 {
1303 int numRate = pWifiPeerInfo->numRate;
1304 struct nlattr *peers = nla_nest_start(vendor_event, i);
1305
1306 if(!peers)
1307 {
1308 hddLog(VOS_TRACE_LEVEL_ERROR,
1309 "%s: peer stats put fail",
1310 __func__);
1311 kfree_skb(vendor_event);
1312 return;
1313 }
1314 if (FALSE == put_wifi_peer_info(
1315 pWifiPeerInfo, vendor_event))
1316 {
1317 hddLog(VOS_TRACE_LEVEL_ERROR,
1318 "%s: put_wifi_peer_info put fail", __func__);
1319 kfree_skb(vendor_event);
1320 return;
1321 }
1322
1323 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8 *)
1324 pWifiPeerStat->peerInfo +
1325 (i * sizeof(tSirWifiPeerInfo)) +
1326 (numRate * sizeof (tSirWifiRateStat)));
1327 nla_nest_end(vendor_event, peers);
1328 }
1329 nla_nest_end(vendor_event, peerInfo);
1330 cfg80211_vendor_cmd_reply(vendor_event);
1331 EXIT();
1332}
1333
1334/*
1335 * hdd_link_layer_process_iface_stats () - This function is called after
1336 * receiving Link Layer Interface statistics from FW.This function converts
1337 * the firmware data to the NL data and sends the same to the kernel/upper
1338 * layers.
1339 */
1340static v_VOID_t hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter,
1341 v_VOID_t *pData)
1342{
1343 tpSirWifiIfaceStat pWifiIfaceStat;
1344 struct sk_buff *vendor_event;
1345 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1346 int status;
1347
1348 ENTER();
1349
1350 status = wlan_hdd_validate_context(pHddCtx);
1351 if (0 != status)
1352 {
1353 return;
1354 }
1355 /*
1356 * Allocate a size of 4096 for the interface stats comprising
1357 * sizeof (tpSirWifiIfaceStat).The size of 4096 is considered
1358 * assuming that all these fit with in the limit.Please take
1359 * a call on the limit based on the data requirements on
1360 * interface statistics.
1361 */
1362 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
1363 LL_STATS_EVENT_BUF_SIZE);
1364 if (!vendor_event)
1365 {
1366 hddLog(VOS_TRACE_LEVEL_ERROR,
1367 FL("cfg80211_vendor_cmd_alloc_reply_skb failed") );
1368 return;
1369 }
1370
1371 pWifiIfaceStat = (tpSirWifiIfaceStat) pData;
1372
1373
1374 if (FALSE == hdd_get_interface_info( pAdapter,
1375 &pWifiIfaceStat->info))
1376 {
1377 hddLog(VOS_TRACE_LEVEL_ERROR,
1378 FL("hdd_get_interface_info get fail") );
1379 kfree_skb(vendor_event);
1380 return;
1381 }
1382
1383 if (FALSE == put_wifi_iface_stats( pAdapter, pWifiIfaceStat,
1384 vendor_event))
1385 {
1386 hddLog(VOS_TRACE_LEVEL_ERROR,
1387 FL("put_wifi_iface_stats fail") );
1388 kfree_skb(vendor_event);
1389 return;
1390 }
1391
1392 hddLog(VOS_TRACE_LEVEL_INFO,
1393 "WMI_LINK_STATS_IFACE Data");
1394
1395 cfg80211_vendor_cmd_reply(vendor_event);
1396 EXIT();
1397}
1398
1399/*
1400 * hdd_link_layer_process_radio_stats () - This function is called after
1401 * receiving Link Layer Radio statistics from FW.This function converts
1402 * the firmware data to the NL data and sends the same to the kernel/upper
1403 * layers.
1404 */
1405static v_VOID_t hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter,
1406 v_VOID_t *pData)
1407{
1408 int status, i;
1409 tpSirWifiRadioStat pWifiRadioStat;
1410 tpSirWifiChannelStats pWifiChannelStats;
1411 struct sk_buff *vendor_event;
1412 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1413 struct nlattr *chList;
1414
1415 ENTER();
1416
1417 status = wlan_hdd_validate_context(pHddCtx);
1418 if (0 != status)
1419 {
1420 return;
1421 }
1422 pWifiRadioStat = (tpSirWifiRadioStat) pData;
1423
1424 hddLog(VOS_TRACE_LEVEL_INFO,
1425 "LL_STATS_RADIO"
1426 " radio is %d onTime is %u "
1427 " txTime is %u rxTime is %u "
1428 " onTimeScan is %u onTimeNbd is %u "
1429 " onTimeEXTScan is %u onTimeRoamScan is %u "
1430 " onTimePnoScan is %u onTimeHs20 is %u "
1431 " numChannels is %u",
1432 pWifiRadioStat->radio, pWifiRadioStat->onTime,
1433 pWifiRadioStat->txTime, pWifiRadioStat->rxTime,
1434 pWifiRadioStat->onTimeScan, pWifiRadioStat->onTimeNbd,
1435 pWifiRadioStat->onTimeEXTScan,
1436 pWifiRadioStat->onTimeRoamScan,
1437 pWifiRadioStat->onTimePnoScan,
1438 pWifiRadioStat->onTimeHs20,
1439 pWifiRadioStat->numChannels);
1440 /*
1441 * Allocate a size of 4096 for the Radio stats comprising
1442 * sizeof (tSirWifiRadioStat) + numChannels * sizeof
1443 * (tSirWifiChannelStats).Each channel data is put with an
1444 * NL attribute.The size of 4096 is considered assuming that
1445 * number of channels shall not exceed beyond 60 with the
1446 * sizeof (tSirWifiChannelStats) being 24 bytes.
1447 */
1448
1449 vendor_event = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy,
1450 LL_STATS_EVENT_BUF_SIZE);
1451 if (!vendor_event)
1452 {
1453 hddLog(VOS_TRACE_LEVEL_ERROR,
1454 FL("cfg80211_vendor_cmd_alloc_reply_skb failed") );
1455 return;
1456 }
1457
1458 if (nla_put_u32(vendor_event,
1459 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE,
1460 QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE_RADIO) ||
1461 nla_put_u32(vendor_event,
1462 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID,
1463 pWifiRadioStat->radio) ||
1464 nla_put_u32(vendor_event,
1465 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME,
1466 pWifiRadioStat->onTime) ||
1467 nla_put_u32(vendor_event,
1468 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME,
1469 pWifiRadioStat->txTime) ||
1470 nla_put_u32(vendor_event,
1471 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME,
1472 pWifiRadioStat->rxTime) ||
1473 nla_put_u32(vendor_event,
1474 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN,
1475 pWifiRadioStat->onTimeScan) ||
1476 nla_put_u32(vendor_event,
1477 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD,
1478 pWifiRadioStat->onTimeNbd) ||
1479 nla_put_u32(vendor_event,
1480 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_EXTSCAN,
1481 pWifiRadioStat->onTimeEXTScan)||
1482 nla_put_u32(vendor_event,
1483 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN,
1484 pWifiRadioStat->onTimeRoamScan) ||
1485 nla_put_u32(vendor_event,
1486 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN,
1487 pWifiRadioStat->onTimePnoScan) ||
1488 nla_put_u32(vendor_event,
1489 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20,
1490 pWifiRadioStat->onTimeHs20) ||
1491 nla_put_u32(vendor_event,
1492 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS,
1493 pWifiRadioStat->numChannels))
1494 {
1495 hddLog(VOS_TRACE_LEVEL_ERROR,
1496 FL("QCA_WLAN_VENDOR_ATTR put fail"));
1497 kfree_skb(vendor_event);
1498 return ;
1499 }
1500
1501 chList = nla_nest_start(vendor_event,
1502 QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO);
1503 if(!chList)
1504 {
1505 hddLog(VOS_TRACE_LEVEL_ERROR,
1506 "%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO put fail",
1507 __func__);
1508 kfree_skb(vendor_event);
1509 return;
1510 }
1511 for (i = 0; i < pWifiRadioStat->numChannels; i++)
1512 {
1513 struct nlattr *chInfo;
1514
1515 pWifiChannelStats = (tpSirWifiChannelStats) ((uint8*)
1516 pWifiRadioStat->channels +
1517 (i * sizeof(tSirWifiChannelStats)));
1518
1519 chInfo = nla_nest_start(vendor_event, i);
1520 if(!chInfo)
1521 {
1522 hddLog(VOS_TRACE_LEVEL_ERROR,
1523 "%s: failed to put chInfo",
1524 __func__);
1525 kfree_skb(vendor_event);
1526 return;
1527 }
1528
1529 if (nla_put_u32(vendor_event,
1530 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH,
1531 pWifiChannelStats->channel.width) ||
1532 nla_put_u32(vendor_event,
1533 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ,
1534 pWifiChannelStats->channel.centerFreq) ||
1535 nla_put_u32(vendor_event,
1536 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0,
1537 pWifiChannelStats->channel.centerFreq0) ||
1538 nla_put_u32(vendor_event,
1539 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1,
1540 pWifiChannelStats->channel.centerFreq1) ||
1541 nla_put_u32(vendor_event,
1542 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME,
1543 pWifiChannelStats->onTime) ||
1544 nla_put_u32(vendor_event,
1545 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME,
1546 pWifiChannelStats->ccaBusyTime))
1547 {
1548 hddLog(VOS_TRACE_LEVEL_ERROR,
1549 FL("cfg80211_vendor_event_alloc failed") );
1550 kfree_skb(vendor_event);
1551 return ;
1552 }
1553 nla_nest_end(vendor_event, chInfo);
1554 }
1555 nla_nest_end(vendor_event, chList);
1556
1557 cfg80211_vendor_cmd_reply(vendor_event);
1558
1559 EXIT();
1560 return;
1561}
1562
1563/*
1564 * hdd_link_layer_stats_ind_callback () - This function is called after
1565 * receiving Link Layer indications from FW.This callback converts the firmware
1566 * data to the NL data and send the same to the kernel/upper layers.
1567 */
1568static void hdd_link_layer_stats_ind_callback ( void *pCtx,
1569 int indType,
1570 void *pRsp, u8 *macAddr)
1571{
1572 hdd_context_t *pHddCtx = (hdd_context_t *)pCtx;
1573 hdd_adapter_t *pAdapter = NULL;
1574 struct hdd_ll_stats_context *context;
1575 tpSirLLStatsResults linkLayerStatsResults = (tpSirLLStatsResults)pRsp;
1576 int status;
1577
1578 ENTER();
1579
1580 status = wlan_hdd_validate_context(pHddCtx);
1581 if (0 != status)
1582 {
1583 return;
1584 }
1585
1586 pAdapter = hdd_get_adapter_by_macaddr(pHddCtx, macAddr);
1587 if (NULL == pAdapter)
1588 {
1589 hddLog(VOS_TRACE_LEVEL_ERROR,
1590 FL(" MAC address %pM does not exist with host"),
1591 macAddr);
1592 return;
1593 }
1594
1595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1596 "%s: Interface: %s LLStats indType: %d", __func__,
1597 pAdapter->dev->name, indType);
1598
1599 switch (indType)
1600 {
1601 case SIR_HAL_LL_STATS_RESULTS_RSP:
1602 {
1603 hddLog(VOS_TRACE_LEVEL_INFO,
1604 "LL_STATS RESP paramID = 0x%x, ifaceId = %u MAC: %pM "
1605 "respId = %u, moreResultToFollow = %u",
1606 linkLayerStatsResults->paramId, linkLayerStatsResults->ifaceId,
1607 macAddr, linkLayerStatsResults->respId,
1608 linkLayerStatsResults->moreResultToFollow);
1609 spin_lock(&hdd_context_lock);
1610 context = &pHddCtx->ll_stats_context;
1611 /* validate response received from target */
1612 if ((context->request_id != linkLayerStatsResults->respId) ||
1613 !(context->request_bitmap & linkLayerStatsResults->paramId))
1614 {
1615 spin_unlock(&hdd_context_lock);
1616 hddLog(LOGE,
1617 FL("Error : Request id %d response id %d request bitmap 0x%x"
1618 "response bitmap 0x%x"),
1619 context->request_id, linkLayerStatsResults->respId,
1620 context->request_bitmap, linkLayerStatsResults->paramId);
1621 return;
1622 }
1623 spin_unlock(&hdd_context_lock);
1624
1625 if ( linkLayerStatsResults->paramId & WMI_LINK_STATS_RADIO )
1626 {
1627 hdd_link_layer_process_radio_stats(pAdapter,
1628 (v_VOID_t *)linkLayerStatsResults->result);
1629 spin_lock(&hdd_context_lock);
1630 context->request_bitmap &= ~(WMI_LINK_STATS_RADIO);
1631 spin_unlock(&hdd_context_lock);
1632 }
1633 else if ( linkLayerStatsResults->paramId & WMI_LINK_STATS_IFACE )
1634 {
1635 hdd_link_layer_process_iface_stats(pAdapter,
1636 (v_VOID_t *)linkLayerStatsResults->result);
1637 spin_lock(&hdd_context_lock);
1638 context->request_bitmap &= ~(WMI_LINK_STATS_IFACE);
1639 spin_unlock(&hdd_context_lock);
1640 }
1641 else if ( linkLayerStatsResults->paramId &
1642 WMI_LINK_STATS_ALL_PEER )
1643 {
1644 hdd_link_layer_process_peer_stats(pAdapter,
1645 (v_VOID_t *)linkLayerStatsResults->result);
1646 spin_lock(&hdd_context_lock);
1647 context->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
1648 spin_unlock(&hdd_context_lock);
1649 } /* WMI_LINK_STATS_ALL_PEER */
1650 else
1651 {
1652 hddLog(VOS_TRACE_LEVEL_ERROR,
1653 FL("INVALID LL_STATS_NOTIFY RESPONSE ***********"));
1654 }
1655
1656 spin_lock(&hdd_context_lock);
1657 /* complete response event if all requests are completed */
1658 if (0 == context->request_bitmap)
1659 complete(&context->response_event);
1660 spin_unlock(&hdd_context_lock);
1661
1662 break;
1663 }
1664 default:
1665 hddLog(VOS_TRACE_LEVEL_ERROR, "invalid event type %d", indType);
1666 break;
1667 }
1668
1669 EXIT();
1670 return;
1671}
1672
1673const struct
1674nla_policy
1675qca_wlan_vendor_ll_set_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX +1] =
1676{
1677 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD] =
1678 { .type = NLA_U32 },
1679 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING] =
1680 { .type = NLA_U32 },
1681};
1682
1683static int __wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1684 struct wireless_dev *wdev,
1685 const void *data,
1686 int data_len)
1687{
1688 int status;
1689 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1];
1690 tSirLLStatsSetReq linkLayerStatsSetReq;
1691 struct net_device *dev = wdev->netdev;
1692 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1693 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1694
1695 ENTER();
1696
1697 status = wlan_hdd_validate_context(pHddCtx);
1698 if (0 != status)
1699 {
1700 return -EINVAL;
1701 }
1702
1703 if (NULL == pAdapter)
1704 {
1705 hddLog(VOS_TRACE_LEVEL_ERROR,
1706 FL("HDD adapter is Null"));
1707 return -ENODEV;
1708 }
1709 /* check the LLStats Capability */
1710 if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
1711 (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
1712 {
1713 hddLog(VOS_TRACE_LEVEL_ERROR,
1714 FL("Link Layer Statistics not supported by Firmware"));
1715 return -EINVAL;
1716 }
1717
1718 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX,
1719 (struct nlattr *)data,
1720 data_len, qca_wlan_vendor_ll_set_policy))
1721 {
1722 hddLog(VOS_TRACE_LEVEL_ERROR, FL() );
1723 return -EINVAL;
1724 }
1725 if (!tb_vendor
1726 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD])
1727 {
1728 hddLog(VOS_TRACE_LEVEL_ERROR, FL("MPDU size Not present"));
1729 return -EINVAL;
1730 }
1731 if (!tb_vendor[
1732 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING])
1733 {
1734 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Stats Gathering Not Present"));
1735 return -EINVAL;
1736 }
1737 // Shall take the request Id if the Upper layers pass. 1 For now.
1738 linkLayerStatsSetReq.reqId = 1;
1739
1740 linkLayerStatsSetReq.mpduSizeThreshold =
1741 nla_get_u32(
1742 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]);
1743
1744 linkLayerStatsSetReq.aggressiveStatisticsGathering =
1745 nla_get_u32(
1746 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]);
1747
1748 vos_mem_copy(linkLayerStatsSetReq.macAddr,
1749 pAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1750
1751
1752 hddLog(VOS_TRACE_LEVEL_INFO,
1753 "LL_STATS_SET reqId = %d, MAC = %pM, mpduSizeThreshold = %d "
1754 "Statistics Gathering = %d ",
1755 linkLayerStatsSetReq.reqId, linkLayerStatsSetReq.macAddr,
1756 linkLayerStatsSetReq.mpduSizeThreshold,
1757 linkLayerStatsSetReq.aggressiveStatisticsGathering);
1758
1759 if (eHAL_STATUS_SUCCESS != sme_SetLinkLayerStatsIndCB(
1760 pHddCtx->hHal,
1761 hdd_link_layer_stats_ind_callback))
1762 {
1763 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
1764 "sme_SetLinkLayerStatsIndCB Failed", __func__);
1765 return -EINVAL;
1766
1767 }
1768
1769 if (eHAL_STATUS_SUCCESS != sme_LLStatsSetReq( pHddCtx->hHal,
1770 &linkLayerStatsSetReq))
1771 {
1772 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
1773 "sme_LLStatsSetReq Failed", __func__);
1774 return -EINVAL;
1775 }
1776
1777 pAdapter->isLinkLayerStatsSet = 1;
1778
1779 EXIT();
1780 return 0;
1781}
1782static int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1783 struct wireless_dev *wdev,
1784 const void *data,
1785 int data_len)
1786{
1787 int ret = 0;
1788
1789 vos_ssr_protect(__func__);
1790 ret = __wlan_hdd_cfg80211_ll_stats_set(wiphy, wdev, data, data_len);
1791 vos_ssr_unprotect(__func__);
1792
1793 return ret;
1794}
1795
1796const struct
1797nla_policy
1798qca_wlan_vendor_ll_get_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX +1] =
1799{
1800 /* Unsigned 32bit value provided by the caller issuing the GET stats
1801 * command. When reporting
1802 * the stats results, the driver uses the same value to indicate
1803 * which GET request the results
1804 * correspond to.
1805 */
1806 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID] = { .type = NLA_U32 },
1807
1808 /* Unsigned 32bit value . bit mask to identify what statistics are
1809 requested for retrieval */
1810 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = { .type = NLA_U32 },
1811};
1812
1813static int __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1814 struct wireless_dev *wdev,
1815 const void *data,
1816 int data_len)
1817{
1818 unsigned long rc;
1819 struct hdd_ll_stats_context *context;
1820 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1821 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1];
1822 tSirLLStatsGetReq linkLayerStatsGetReq;
1823 struct net_device *dev = wdev->netdev;
1824 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1825 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
1826 int status;
1827
1828 ENTER();
1829
1830 status = wlan_hdd_validate_context(pHddCtx);
1831 if (0 != status)
1832 {
1833 return -EINVAL ;
1834 }
1835
1836 if (NULL == pAdapter)
1837 {
1838 hddLog(VOS_TRACE_LEVEL_FATAL,
1839 "%s: HDD adapter is Null", __func__);
1840 return -ENODEV;
1841 }
1842
1843 if (pHddStaCtx == NULL)
1844 {
1845 hddLog(VOS_TRACE_LEVEL_FATAL,
1846 "%s: HddStaCtx is Null", __func__);
1847 return -ENODEV;
1848 }
1849
1850 /* check the LLStats Capability */
1851 if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
1852 (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
1853 {
1854 hddLog(VOS_TRACE_LEVEL_ERROR,
1855 FL("Link Layer Statistics not supported by Firmware"));
1856 return -EINVAL;
1857 }
1858
1859
1860 if (!pAdapter->isLinkLayerStatsSet)
1861 {
1862 hddLog(VOS_TRACE_LEVEL_FATAL,
1863 "%s: isLinkLayerStatsSet : %d",
1864 __func__, pAdapter->isLinkLayerStatsSet);
1865 return -EINVAL;
1866 }
1867
1868 if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario)
1869 {
1870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1871 "%s: Roaming in progress, so unable to proceed this request", __func__);
1872 return -EBUSY;
1873 }
1874
1875 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX,
1876 (struct nlattr *)data,
1877 data_len, qca_wlan_vendor_ll_get_policy))
1878 {
1879 hddLog(VOS_TRACE_LEVEL_ERROR, FL() );
1880 return -EINVAL;
1881 }
1882
1883 if (!tb_vendor
1884 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID])
1885 {
1886 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request Id Not present"));
1887 return -EINVAL;
1888 }
1889
1890 if (!tb_vendor
1891 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK])
1892 {
1893 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Req Mask Not present"));
1894 return -EINVAL;
1895 }
1896
1897
1898 linkLayerStatsGetReq.reqId =
1899 nla_get_u32( tb_vendor[
1900 QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]);
1901 linkLayerStatsGetReq.paramIdMask =
1902 nla_get_u32( tb_vendor[
1903 QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]);
1904
1905 vos_mem_copy(linkLayerStatsGetReq.macAddr,
1906 pAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
1907
1908 hddLog(VOS_TRACE_LEVEL_INFO,
1909 "LL_STATS_GET reqId = %d, MAC = %pM, paramIdMask = %d",
1910 linkLayerStatsGetReq.reqId, linkLayerStatsGetReq.macAddr,
1911 linkLayerStatsGetReq.paramIdMask);
1912
1913 spin_lock(&hdd_context_lock);
1914 context = &pHddCtx->ll_stats_context;
1915 context->request_id = linkLayerStatsGetReq.reqId;
1916 context->request_bitmap = linkLayerStatsGetReq.paramIdMask;
1917 INIT_COMPLETION(context->response_event);
1918 spin_unlock(&hdd_context_lock);
1919
1920 if (eHAL_STATUS_SUCCESS != sme_LLStatsGetReq( pHddCtx->hHal,
1921 &linkLayerStatsGetReq))
1922 {
1923 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
1924 "sme_LLStatsGetReq Failed", __func__);
1925 return -EINVAL;
1926 }
1927
1928 rc = wait_for_completion_timeout(&context->response_event,
1929 msecs_to_jiffies(WLAN_WAIT_TIME_LL_STATS));
1930 if (!rc)
1931 {
1932 hddLog(LOGE,
1933 FL("Target response timed out request id %d request bitmap 0x%x"),
1934 context->request_id, context->request_bitmap);
1935 return -ETIMEDOUT;
1936 }
1937
1938 EXIT();
1939 return 0;
1940}
1941
1942static int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1943 struct wireless_dev *wdev,
1944 const void *data,
1945 int data_len)
1946{
1947 int ret = 0;
1948
1949 vos_ssr_protect(__func__);
1950 ret = __wlan_hdd_cfg80211_ll_stats_get(wiphy, wdev, data, data_len);
1951 vos_ssr_unprotect(__func__);
1952
1953 return ret;
1954}
1955
1956const struct
1957nla_policy
1958qca_wlan_vendor_ll_clr_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX +1] =
1959{
1960 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] = {.type = NLA_U32 },
1961 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ] = {.type = NLA_U8 },
1962 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK] = {.type = NLA_U32 },
1963 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP] = {.type = NLA_U8 },
1964};
1965
1966static int __wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
1967 struct wireless_dev *wdev,
1968 const void *data,
1969 int data_len)
1970{
1971 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1972 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
1973 tSirLLStatsClearReq linkLayerStatsClearReq;
1974 struct net_device *dev = wdev->netdev;
1975 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1976 u32 statsClearReqMask;
1977 u8 stopReq;
1978 int status;
1979
1980 ENTER();
1981
1982 status = wlan_hdd_validate_context(pHddCtx);
1983 if (0 != status)
1984 {
1985 return -EINVAL;
1986 }
1987
1988 if (NULL == pAdapter)
1989 {
1990 hddLog(VOS_TRACE_LEVEL_FATAL,
1991 "%s: HDD adapter is Null", __func__);
1992 return -ENODEV;
1993 }
1994 /* check the LLStats Capability */
1995 if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
1996 (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
1997 {
1998 hddLog(VOS_TRACE_LEVEL_ERROR,
1999 FL("Enable LLStats Capability"));
2000 return -EINVAL;
2001 }
2002
2003 if (!pAdapter->isLinkLayerStatsSet)
2004 {
2005 hddLog(VOS_TRACE_LEVEL_FATAL,
2006 "%s: isLinkLayerStatsSet : %d",
2007 __func__, pAdapter->isLinkLayerStatsSet);
2008 return -EINVAL;
2009 }
2010
2011 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
2012 (struct nlattr *)data,
2013 data_len, qca_wlan_vendor_ll_clr_policy))
2014 {
2015 hddLog(VOS_TRACE_LEVEL_ERROR, FL() );
2016 return -EINVAL;
2017 }
2018
2019 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] ||
2020
2021 !tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ])
2022 {
2023 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Error in LL_STATS CLR CONFIG PARA") );
2024 return -EINVAL;
2025
2026 }
2027
2028
2029 statsClearReqMask = linkLayerStatsClearReq.statsClearReqMask =
2030 nla_get_u32(
2031 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK]);
2032
2033 stopReq = linkLayerStatsClearReq.stopReq =
2034 nla_get_u8(
2035 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]);
2036
2037 // Shall take the request Id if the Upper layers pass. 1 For now.
2038 linkLayerStatsClearReq.reqId = 1;
2039
2040 vos_mem_copy(linkLayerStatsClearReq.macAddr,
2041 pAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
2042
2043 hddLog(VOS_TRACE_LEVEL_INFO,
2044 "LL_STATS_CLEAR reqId = %d, MAC = %pM,"
2045 "statsClearReqMask = 0x%X, stopReq = %d",
2046 linkLayerStatsClearReq.reqId,
2047 linkLayerStatsClearReq.macAddr,
2048 linkLayerStatsClearReq.statsClearReqMask,
2049 linkLayerStatsClearReq.stopReq);
2050
2051 if (eHAL_STATUS_SUCCESS == sme_LLStatsClearReq(pHddCtx->hHal,
2052 &linkLayerStatsClearReq))
2053 {
2054 struct sk_buff *temp_skbuff;
2055 hdd_station_ctx_t *pHddStaCtx;
2056
2057 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2058 if (VOS_STATUS_SUCCESS !=
2059 WLANTL_ClearInterfaceStats((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
2060 pHddStaCtx->conn_info.staId[0], statsClearReqMask))
2061 {
2062 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
2063 "WLANTL_ClearInterfaceStats Failed", __func__);
2064 return -EINVAL;
2065 }
2066 if ((statsClearReqMask & WIFI_STATS_IFACE_AC) ||
2067 (statsClearReqMask & WIFI_STATS_IFACE)) {
2068 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VO] = 0;
2069 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_VI] = 0;
2070 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BE] = 0;
2071 pAdapter->hdd_stats.hddTxRxStats.txMcast[WLANTL_AC_BK] = 0;
2072 }
2073
2074 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2075 2 * sizeof(u32) +
2076 NLMSG_HDRLEN);
2077
2078 if (temp_skbuff != NULL)
2079 {
2080
2081 if (nla_put_u32(temp_skbuff,
2082 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK,
2083 statsClearReqMask) ||
2084 nla_put_u32(temp_skbuff,
2085 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP,
2086 stopReq))
2087 {
2088 hddLog(VOS_TRACE_LEVEL_ERROR, FL("LL_STATS_CLR put fail"));
2089 kfree_skb(temp_skbuff);
2090 return -EINVAL;
2091 }
2092 /* If the ask is to stop the stats collection as part of clear
2093 * (stopReq = 1) , ensure that no further requests of get
2094 * go to the firmware by having isLinkLayerStatsSet set to 0.
2095 * However it the stopReq as part of the clear request is 0 ,
2096 * the request to get the statistics are honoured as in this
2097 * case the firmware is just asked to clear the statistics.
2098 */
2099 if (linkLayerStatsClearReq.stopReq == 1)
2100 pAdapter->isLinkLayerStatsSet = 0;
2101 return cfg80211_vendor_cmd_reply(temp_skbuff);
2102 }
2103 return -ENOMEM;
2104 }
2105
2106 EXIT();
2107 return -EINVAL;
2108}
2109static int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
2110 struct wireless_dev *wdev,
2111 const void *data,
2112 int data_len)
2113{
2114 int ret = 0;
2115
2116 vos_ssr_protect(__func__);
2117 ret = __wlan_hdd_cfg80211_ll_stats_clear(wiphy, wdev, data, data_len);
2118 vos_ssr_unprotect(__func__);
2119
2120 return ret;
2121
2122
2123}
2124#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
2125
2126#ifdef WLAN_FEATURE_EXTSCAN
2127static const struct nla_policy
2128wlan_hdd_extscan_config_policy
2129 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] =
2130{
2131 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] =
2132 { .type = NLA_U32 },
2133 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] =
2134 { .type = NLA_U32 },
SaidiReddy Yenuga25a3b152017-05-26 18:19:31 +05302135 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS] =
2136 { .type = NLA_U32 },
chrmhoffmannbb97ca42017-05-13 21:27:44 +02002137 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 },
2138 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] =
2139 { .type = NLA_U32 },
2140 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = { .type = NLA_U8 },
2141 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = { .type = NLA_U8 },
2142
2143 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = { .type = NLA_U8 },
2144 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = { .type = NLA_U8 },
2145 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = { .type = NLA_U32 },
2146 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] =
2147 { .type = NLA_U8 },
2148 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] =
2149 { .type = NLA_U32 },
2150 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] =
2151 { .type = NLA_U32 },
2152 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] =
2153 { .type = NLA_U32 },
2154 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD] =
2155 { .type = NLA_U8 },
2156 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] =
2157 { .type = NLA_U8 },
2158 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] =
2159 { .type = NLA_U8 },
2160
2161 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] =
2162 { .type = NLA_U32 },
2163 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] =
2164 { .type = NLA_UNSPEC },
2165 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] =
2166 { .type = NLA_S32 },
2167 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] =
2168 { .type = NLA_S32 },
2169 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] =
2170 { .type = NLA_U32 },
2171 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] =
2172 { .type = NLA_U32 },
2173 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] =
2174 { .type = NLA_U32 },
2175 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]
2176 = { .type = NLA_U32 },
2177 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] =
2178 { .type = NLA_U32 },
2179 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type =
2180 NLA_U32 },
2181};
2182
2183static void wlan_hdd_cfg80211_extscan_get_capabilities_ind(void *ctx, void *pMsg)
2184{
2185 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2186 struct sk_buff *skb = NULL;
2187 tpSirEXTScanCapabilitiesEvent pData =
2188 (tpSirEXTScanCapabilitiesEvent) pMsg;
2189
2190 ENTER();
2191
2192 if (wlan_hdd_validate_context(pHddCtx))
2193 {
2194 return;
2195 }
2196
2197 if (!pMsg)
2198 {
2199 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2200 return;
2201 }
2202 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2203#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2204 NULL,
2205#endif
2206 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2207 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX,
2208 GFP_KERNEL);
2209
2210 if (!skb) {
2211 hddLog(VOS_TRACE_LEVEL_ERROR,
2212 FL("cfg80211_vendor_event_alloc failed"));
2213 return;
2214 }
2215
2216 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2217 hddLog(VOS_TRACE_LEVEL_INFO, "Scan cache size (%u)", pData->scanCacheSize);
2218 hddLog(VOS_TRACE_LEVEL_INFO, "Scan buckets (%u)", pData->scanBuckets);
2219 hddLog(VOS_TRACE_LEVEL_INFO, "Max AP per scan (%u)", pData->maxApPerScan);
2220 hddLog(VOS_TRACE_LEVEL_INFO, "maxRssiSampleSize (%u)",
2221 pData->maxRssiSampleSize);
2222 hddLog(VOS_TRACE_LEVEL_INFO, "maxScanReportingThreshold (%u)",
2223 pData->maxScanReportingThreshold);
2224 hddLog(VOS_TRACE_LEVEL_INFO, "maxHotlistAPs (%u)", pData->maxHotlistAPs);
2225 hddLog(VOS_TRACE_LEVEL_INFO, "maxSignificantWifiChangeAPs (%u)",
2226 pData->maxSignificantWifiChangeAPs);
2227 hddLog(VOS_TRACE_LEVEL_INFO, "maxBsidHistoryEntries (%u)",
2228 pData->maxBsidHistoryEntries);
2229
2230 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2231 pData->requestId) ||
2232 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status) ||
2233 nla_put_u32(skb,
2234 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE,
2235 pData->scanCacheSize) ||
2236 nla_put_u32(skb,
2237 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS,
2238 pData->scanBuckets) ||
2239 nla_put_u32(skb,
2240 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN,
2241 pData->maxApPerScan) ||
2242 nla_put_u32(skb,
2243 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE,
2244 pData->maxRssiSampleSize) ||
2245 nla_put_u32(skb,
2246 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD,
2247 pData->maxScanReportingThreshold) ||
2248 nla_put_u32(skb,
2249 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_APS,
2250 pData->maxHotlistAPs) ||
2251 nla_put_u32(skb,
2252 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS,
2253 pData->maxSignificantWifiChangeAPs) ||
2254 nla_put_u32(skb,
2255 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES,
2256 pData->maxBsidHistoryEntries)) {
2257 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2258 goto nla_put_failure;
2259 }
2260
2261 cfg80211_vendor_event(skb, GFP_KERNEL);
2262 EXIT();
2263 return;
2264
2265nla_put_failure:
2266 kfree_skb(skb);
2267 return;
2268}
2269
2270
2271static void wlan_hdd_cfg80211_extscan_start_rsp(void *ctx, void *pMsg)
2272{
2273 tpSirEXTScanStartRspParams pData = (tpSirEXTScanStartRspParams) pMsg;
2274 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2275 struct sk_buff *skb = NULL;
2276 tpAniSirGlobal pMac = PMAC_STRUCT( pHddCtx->hHal );
2277
2278 ENTER();
2279
2280 if (wlan_hdd_validate_context(pHddCtx)){
2281 return;
2282 }
2283 if (!pMsg)
2284 {
2285 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2286 return;
2287 }
2288
2289 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2290#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2291 NULL,
2292#endif
2293 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2294 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX,
2295 GFP_KERNEL);
2296
2297 if (!skb) {
2298 hddLog(VOS_TRACE_LEVEL_ERROR,
2299 FL("cfg80211_vendor_event_alloc failed"));
2300 return;
2301 }
2302 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2303 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2304 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2305
2306 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2307 pData->requestId) ||
2308 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2309 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2310 goto nla_put_failure;
2311 }
2312
2313 /*
2314 * Store the Request ID for comparing with the requestID obtained
2315 * in other requests.HDD shall return a failure is the extscan_stop
2316 * request is issued with a different requestId as that of the
2317 * extscan_start request. Also, This requestId shall be used while
2318 * indicating the full scan results to the upper layers.
2319 * The requestId is stored with the assumption that the firmware
2320 * shall return the ext scan start request's requestId in ext scan
2321 * start response.
2322 */
2323 if (pData->status == 0)
2324 pMac->sme.extScanStartReqId = pData->requestId;
2325
2326
2327 cfg80211_vendor_event(skb, GFP_KERNEL);
2328 EXIT();
2329 return;
2330
2331nla_put_failure:
2332 kfree_skb(skb);
2333 return;
2334}
2335
2336
2337static void wlan_hdd_cfg80211_extscan_stop_rsp(void *ctx, void *pMsg)
2338{
2339 tpSirEXTScanStopRspParams pData = (tpSirEXTScanStopRspParams) pMsg;
2340 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2341 struct sk_buff *skb = NULL;
2342
2343 ENTER();
2344
2345 if (wlan_hdd_validate_context(pHddCtx)){
2346 return;
2347 }
2348 if (!pMsg)
2349 {
2350 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2351 return;
2352 }
2353
2354 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2355#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2356 NULL,
2357#endif
2358 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2359 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX,
2360 GFP_KERNEL);
2361
2362 if (!skb) {
2363 hddLog(VOS_TRACE_LEVEL_ERROR,
2364 FL("cfg80211_vendor_event_alloc failed"));
2365 return;
2366 }
2367 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2368 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2369
2370 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2371 pData->requestId) ||
2372 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2373 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2374 goto nla_put_failure;
2375 }
2376
2377 cfg80211_vendor_event(skb, GFP_KERNEL);
2378 EXIT();
2379 return;
2380
2381nla_put_failure:
2382 kfree_skb(skb);
2383 return;
2384}
2385
2386
2387static void wlan_hdd_cfg80211_extscan_set_bss_hotlist_rsp(void *ctx,
2388 void *pMsg)
2389{
2390 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2391 struct sk_buff *skb = NULL;
2392 tpSirEXTScanSetBssidHotListRspParams pData =
2393 (tpSirEXTScanSetBssidHotListRspParams) pMsg;
2394
2395 ENTER();
2396
2397 if (wlan_hdd_validate_context(pHddCtx)){
2398 return;
2399 }
2400 if (!pMsg)
2401 {
2402 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2403 return;
2404 }
2405
2406 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2407#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2408 NULL,
2409#endif
2410 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2411 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX,
2412 GFP_KERNEL);
2413
2414 if (!skb) {
2415 hddLog(VOS_TRACE_LEVEL_ERROR,
2416 FL("cfg80211_vendor_event_alloc failed"));
2417 return;
2418 }
2419 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2420 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2421 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2422
2423 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2424 pData->requestId) ||
2425 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2426 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2427 goto nla_put_failure;
2428 }
2429
2430 cfg80211_vendor_event(skb, GFP_KERNEL);
2431 EXIT();
2432 return;
2433
2434nla_put_failure:
2435 kfree_skb(skb);
2436 return;
2437}
2438
2439static void wlan_hdd_cfg80211_extscan_reset_bss_hotlist_rsp(void *ctx,
2440 void *pMsg)
2441{
2442 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2443 struct sk_buff *skb = NULL;
2444 tpSirEXTScanResetBssidHotlistRspParams pData =
2445 (tpSirEXTScanResetBssidHotlistRspParams) pMsg;
2446
2447 ENTER();
2448
2449 if (wlan_hdd_validate_context(pHddCtx)) {
2450 return;
2451 }
2452 if (!pMsg)
2453 {
2454 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2455 return;
2456 }
2457
2458 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2459#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2460 NULL,
2461#endif
2462 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2463 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX,
2464 GFP_KERNEL);
2465
2466 if (!skb) {
2467 hddLog(VOS_TRACE_LEVEL_ERROR,
2468 FL("cfg80211_vendor_event_alloc failed"));
2469 return;
2470 }
2471 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2472 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2473
2474 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2475 pData->requestId) ||
2476 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2477 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2478 goto nla_put_failure;
2479 }
2480
2481 cfg80211_vendor_event(skb, GFP_KERNEL);
2482 EXIT();
2483 return;
2484
2485nla_put_failure:
2486 kfree_skb(skb);
2487 return;
2488}
2489
2490
2491static void wlan_hdd_cfg80211_extscan_set_signf_wifi_change_rsp(void *ctx,
2492 void *pMsg)
2493{
2494 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2495 struct sk_buff *skb = NULL;
2496 tpSirEXTScanSetSignificantChangeRspParams pData =
2497 (tpSirEXTScanSetSignificantChangeRspParams) pMsg;
2498
2499 ENTER();
2500
2501 if (wlan_hdd_validate_context(pHddCtx)) {
2502 return;
2503 }
2504 if (!pMsg)
2505 {
2506 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2507 return;
2508 }
2509
2510 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2512 NULL,
2513#endif
2514 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2515 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX,
2516 GFP_KERNEL);
2517
2518 if (!skb) {
2519 hddLog(VOS_TRACE_LEVEL_ERROR,
2520 FL("cfg80211_vendor_event_alloc failed"));
2521 return;
2522 }
2523 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2524 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2525 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2526
2527 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2528 pData->requestId) ||
2529 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2530 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2531 goto nla_put_failure;
2532 }
2533
2534 cfg80211_vendor_event(skb, GFP_KERNEL);
2535 EXIT();
2536 return;
2537
2538nla_put_failure:
2539 kfree_skb(skb);
2540 return;
2541}
2542
2543
2544static void wlan_hdd_cfg80211_extscan_reset_signf_wifi_change_rsp(void *ctx,
2545 void *pMsg)
2546{
2547 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2548 struct sk_buff *skb = NULL;
2549 tpSirEXTScanResetSignificantChangeRspParams pData =
2550 (tpSirEXTScanResetSignificantChangeRspParams) pMsg;
2551
2552 ENTER();
2553
2554 if (wlan_hdd_validate_context(pHddCtx)) {
2555 return;
2556 }
2557 if (!pMsg)
2558 {
2559 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2560 return;
2561 }
2562
2563 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2564#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2565 NULL,
2566#endif
2567 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2568 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX,
2569 GFP_KERNEL);
2570
2571 if (!skb) {
2572 hddLog(VOS_TRACE_LEVEL_ERROR,
2573 FL("cfg80211_vendor_event_alloc failed"));
2574 return;
2575 }
2576 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2577 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2578 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2579
2580 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2581 pData->requestId) ||
2582 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2583 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2584 goto nla_put_failure;
2585 }
2586
2587 cfg80211_vendor_event(skb, GFP_KERNEL);
2588 EXIT();
2589 return;
2590
2591nla_put_failure:
2592 kfree_skb(skb);
2593 return;
2594}
2595
2596static void wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
2597 void *pMsg)
2598{
2599 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2600 struct sk_buff *skb = NULL;
2601 tANI_U32 i = 0, j, resultsPerEvent;
2602 tANI_S32 totalResults;
2603 tpSirWifiScanResultEvent pData = (tpSirWifiScanResultEvent) pMsg;
2604 tpSirWifiScanResult pSirWifiScanResult;
2605
2606 ENTER();
2607
2608 if (wlan_hdd_validate_context(pHddCtx)) {
2609 return;
2610 }
2611 if (!pMsg)
2612 {
2613 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2614 return;
2615 }
2616
2617 totalResults = pData->numOfAps;
2618 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2619 hddLog(VOS_TRACE_LEVEL_INFO, "Num results (%u)", pData->numOfAps);
2620 hddLog(VOS_TRACE_LEVEL_INFO, "More Data (%u)", pData->moreData);
2621
2622 do{
2623 resultsPerEvent = ((totalResults >= EXTSCAN_MAX_CACHED_RESULTS_PER_IND) ?
2624 EXTSCAN_MAX_CACHED_RESULTS_PER_IND : totalResults);
2625 totalResults -= EXTSCAN_MAX_CACHED_RESULTS_PER_IND;
2626
2627 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2628#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2629 NULL,
2630#endif
2631 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2632 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX,
2633 GFP_KERNEL);
2634
2635 if (!skb) {
2636 hddLog(VOS_TRACE_LEVEL_ERROR,
2637 FL("cfg80211_vendor_event_alloc failed"));
2638 return;
2639 }
2640
2641 hddLog(VOS_TRACE_LEVEL_INFO, "resultsPerEvent (%u)", resultsPerEvent);
2642
2643 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2644 pData->requestId) ||
2645 nla_put_u32(skb,
2646 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2647 resultsPerEvent)) {
2648 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2649 goto fail;
2650 }
2651 if (nla_put_u8(skb,
2652 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
2653 pData->moreData ? 1 : (totalResults > 0 ? 1 : 0 )))
2654 {
2655 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2656 goto fail;
2657 }
2658
2659 if (resultsPerEvent) {
2660 struct nlattr *aps;
2661
2662 aps = nla_nest_start(skb,
2663 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
2664 if (!aps)
2665 {
2666 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2667 goto fail;
2668 }
2669
2670 for (j = 0; j < resultsPerEvent; j++, i++) {
2671 struct nlattr *ap;
2672 pSirWifiScanResult = (tpSirWifiScanResult) ((tANI_U8 *)
2673 pData->ap + ( i* sizeof(tSirWifiScanResult)));
2674
2675 hddLog(VOS_TRACE_LEVEL_INFO, "[index=%u] Timestamp(%llu) "
2676 "Ssid (%s)"
2677 "Bssid: %pM "
2678 "Channel (%u)"
2679 "Rssi (%d)"
2680 "RTT (%u)"
2681 "RTT_SD (%u)",
2682 i,
2683 pSirWifiScanResult->ts,
2684 pSirWifiScanResult->ssid,
2685 pSirWifiScanResult->bssid,
2686 pSirWifiScanResult->channel,
2687 pSirWifiScanResult->rssi,
2688 pSirWifiScanResult->rtt,
2689 pSirWifiScanResult->rtt_sd);
2690
2691 ap = nla_nest_start(skb, j + 1);
2692 if (!ap)
2693 {
2694 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2695 goto fail;
2696 }
2697
2698 if (nla_put_u64(skb,
2699 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
2700 pSirWifiScanResult->ts) )
2701 {
2702 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2703 goto fail;
2704 }
2705 if (nla_put(skb,
2706 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
2707 sizeof(pSirWifiScanResult->ssid),
2708 pSirWifiScanResult->ssid) )
2709 {
2710 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2711 goto fail;
2712 }
2713 if (nla_put(skb,
2714 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
2715 sizeof(pSirWifiScanResult->bssid),
2716 pSirWifiScanResult->bssid) )
2717 {
2718 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2719 goto fail;
2720 }
2721 if (nla_put_u32(skb,
2722 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
2723 pSirWifiScanResult->channel) )
2724 {
2725 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2726 goto fail;
2727 }
2728 if (nla_put_s32(skb,
2729 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
2730 pSirWifiScanResult->rssi) )
2731 {
2732 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2733 goto fail;
2734 }
2735 if (nla_put_u32(skb,
2736 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
2737 pSirWifiScanResult->rtt) )
2738 {
2739 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2740 goto fail;
2741 }
2742 if (nla_put_u32(skb,
2743 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
2744 pSirWifiScanResult->rtt_sd))
2745 {
2746 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2747 goto fail;
2748 }
2749
2750 nla_nest_end(skb, ap);
2751 }
2752 nla_nest_end(skb, aps);
2753
2754 }
2755 cfg80211_vendor_event(skb, GFP_KERNEL);
2756 } while (totalResults > 0);
2757
2758 EXIT();
2759 return;
2760fail:
2761 kfree_skb(skb);
2762 return;
2763}
2764
2765static void wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
2766 void *pMsg)
2767{
2768 tpSirWifiScanResultEvent pData = (tpSirWifiScanResultEvent) pMsg;
2769 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2770 struct sk_buff *skb = NULL;
2771 tANI_U32 i;
2772
2773 ENTER();
2774
2775 if (wlan_hdd_validate_context(pHddCtx)) {
2776 return;
2777 }
2778 if (!pMsg)
2779 {
2780 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2781 return;
2782 }
2783
2784 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2785#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2786 NULL,
2787#endif
2788 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2789 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX,
2790 GFP_KERNEL);
2791
2792 if (!skb) {
2793 hddLog(VOS_TRACE_LEVEL_ERROR,
2794 FL("cfg80211_vendor_event_alloc failed"));
2795 return;
2796 }
2797 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2798 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2799 hddLog(VOS_TRACE_LEVEL_INFO, "Num results (%u)", pData->numOfAps);
2800 hddLog(VOS_TRACE_LEVEL_INFO, "More Data (%u)", pData->moreData);
2801
2802 for (i = 0; i < pData->numOfAps; i++) {
2803 hddLog(VOS_TRACE_LEVEL_INFO, "[index=%u] Timestamp(0x%lld) "
2804 "Ssid (%s) "
2805 "Bssid (" MAC_ADDRESS_STR ") "
2806 "Channel (%u) "
2807 "Rssi (%d) "
2808 "RTT (%u) "
2809 "RTT_SD (%u) ",
2810 i,
2811 pData->ap[i].ts,
2812 pData->ap[i].ssid,
2813 MAC_ADDR_ARRAY(pData->ap[i].bssid),
2814 pData->ap[i].channel,
2815 pData->ap[i].rssi,
2816 pData->ap[i].rtt,
2817 pData->ap[i].rtt_sd);
2818 }
2819
2820 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2821 pData->requestId) ||
2822 nla_put_u32(skb,
2823 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2824 pData->numOfAps)) {
2825 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2826 goto fail;
2827 }
2828 if (pData->numOfAps) {
2829 struct nlattr *aps;
2830
2831 aps = nla_nest_start(skb,
2832 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
2833 if (!aps)
2834 goto fail;
2835
2836 for (i = 0; i < pData->numOfAps; i++) {
2837 struct nlattr *ap;
2838
2839 ap = nla_nest_start(skb, i + 1);
2840 if (!ap)
2841 goto fail;
2842
2843 if (nla_put_u64(skb,
2844 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
2845 pData->ap[i].ts) ||
2846 nla_put(skb,
2847 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
2848 sizeof(pData->ap[i].ssid),
2849 pData->ap[i].ssid) ||
2850 nla_put(skb,
2851 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
2852 sizeof(pData->ap[i].bssid),
2853 pData->ap[i].bssid) ||
2854 nla_put_u32(skb,
2855 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
2856 pData->ap[i].channel) ||
2857 nla_put_s32(skb,
2858 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
2859 pData->ap[i].rssi) ||
2860 nla_put_u32(skb,
2861 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
2862 pData->ap[i].rtt) ||
2863 nla_put_u32(skb,
2864 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
2865 pData->ap[i].rtt_sd))
2866 goto fail;
2867
2868 nla_nest_end(skb, ap);
2869 }
2870 nla_nest_end(skb, aps);
2871
2872 if (nla_put_u8(skb,
2873 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
2874 pData->moreData))
2875 goto fail;
2876 }
2877
2878 cfg80211_vendor_event(skb, GFP_KERNEL);
2879 EXIT();
2880 return;
2881
2882fail:
2883 kfree_skb(skb);
2884 return;
2885
2886}
2887static void wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(void *ctx,
2888 void *pMsg)
2889{
2890 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2891 struct sk_buff *skb = NULL;
2892 tANI_U32 i, j;
2893 tpSirWifiSignificantChangeEvent pData =
2894 (tpSirWifiSignificantChangeEvent) pMsg;
2895
2896 ENTER();
2897
2898 if (wlan_hdd_validate_context(pHddCtx)) {
2899 return;
2900 }
2901 if (!pMsg)
2902 {
2903 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
2904 return;
2905 }
2906
2907 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2908#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2909 NULL,
2910#endif
2911 EXTSCAN_EVENT_BUF_SIZE,
2912 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
2913 GFP_KERNEL);
2914
2915 if (!skb) {
2916 hddLog(VOS_TRACE_LEVEL_ERROR,
2917 FL("cfg80211_vendor_event_alloc failed"));
2918 return;
2919 }
2920 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2921 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2922 hddLog(VOS_TRACE_LEVEL_INFO, "total List Size %u ", pData->numSigRssiBss);
2923 hddLog(VOS_TRACE_LEVEL_INFO, " CUrrent List size (%u)",
2924 pData->numSigRssiBss);
2925 hddLog(VOS_TRACE_LEVEL_INFO, "moreData (%u)", pData->moreData);
2926
2927 for (i = 0; i < pData->numSigRssiBss; i++) {
2928 hddLog(VOS_TRACE_LEVEL_INFO , "Rssi List [%d] BSSID: (%pM) Channel %u "
2929 " num RSSI %u ",
2930 i, pData->sigRssiResult[i].bssid,
2931 pData->sigRssiResult[i].channel,
2932 pData->sigRssiResult[i].numRssi);
2933
2934 for (j = 0; j < pData->sigRssiResult[i].numRssi; j++){
2935
2936 hddLog(VOS_TRACE_LEVEL_INFO,
2937 " [%d]",
2938 pData->sigRssiResult[i].rssi[j]);
2939
2940 }
2941 }
2942
2943
2944 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2945 pData->requestId) ||
2946 nla_put_u32(skb,
2947 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2948 pData->numSigRssiBss)) {
2949 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2950 goto fail;
2951 }
2952
2953 if (pData->numSigRssiBss) {
2954 struct nlattr *aps;
2955 aps = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
2956 if (!aps)
2957 goto fail;
2958 for (i = 0; i < pData->numSigRssiBss; i++) {
2959 struct nlattr *ap;
2960
2961 ap = nla_nest_start(skb, i);
2962 if (!ap)
2963 goto fail;
2964 if (nla_put(skb,
2965 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
2966 sizeof(tSirMacAddr), pData->sigRssiResult[i].bssid) ||
2967 nla_put_u32(skb,
2968 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
2969 pData->sigRssiResult[i].channel) ||
2970 nla_put_u32(skb,
2971 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
2972 pData->sigRssiResult[i].numRssi) ||
2973 nla_put(skb,
2974 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
2975 sizeof(s32) * pData->sigRssiResult[i].numRssi,
2976 pData->sigRssiResult[i].rssi))
2977 goto fail;
2978 nla_nest_end(skb, ap);
2979 }
2980 nla_nest_end(skb, aps);
2981 if (nla_put_u8(skb,
2982 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
2983 pData->moreData))
2984 goto fail;
2985 }
2986 cfg80211_vendor_event(skb, GFP_KERNEL);
2987 EXIT();
2988 return;
2989fail:
2990 kfree_skb(skb);
2991 return;
2992}
2993
2994static void wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
2995 void *pMsg)
2996{
2997 struct sk_buff *skb;
2998 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2999 tpSirWifiFullScanResultEvent pData =
3000 (tpSirWifiFullScanResultEvent) (pMsg);
3001
3002 ENTER();
3003
3004 if (wlan_hdd_validate_context(pHddCtx)) {
3005 return;
3006 }
3007 if (!pMsg)
3008 {
3009 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
3010 return;
3011 }
3012
3013 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
3014#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
3015 NULL,
3016#endif
3017 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
3018 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
3019 GFP_KERNEL);
3020
3021 if (!skb) {
3022 hddLog(VOS_TRACE_LEVEL_ERROR,
3023 FL("cfg80211_vendor_event_alloc failed"));
3024 return;
3025 }
3026
3027 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
3028 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%u)"), pData->requestId);
3029 hddLog(VOS_TRACE_LEVEL_INFO, FL("More Data (%u)"), pData->moreData);
3030 hddLog(VOS_TRACE_LEVEL_INFO, FL("AP Info: Timestamp(0x%llX) "
3031 "Ssid (%s)"
3032 "Bssid (" MAC_ADDRESS_STR ")"
3033 "Channel (%u)"
3034 "Rssi (%d)"
3035 "RTT (%u)"
3036 "RTT_SD (%u)"),
3037 pData->ap.ts,
3038 pData->ap.ssid,
3039 MAC_ADDR_ARRAY(pData->ap.bssid),
3040 pData->ap.channel,
3041 pData->ap.rssi,
3042 pData->ap.rtt,
3043 pData->ap.rtt_sd);
3044 hddLog(VOS_TRACE_LEVEL_INFO, "IE Length (%u)", pData->ieLength);
3045 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
3046 pData->requestId) ||
3047 nla_put_u64(skb,
3048 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
3049 pData->ap.ts) ||
3050 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
3051 sizeof(pData->ap.ssid),
3052 pData->ap.ssid) ||
3053 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
3054 WNI_CFG_BSSID_LEN,
3055 pData->ap.bssid) ||
3056 nla_put_u32(skb,
3057 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
3058 pData->ap.channel) ||
3059 nla_put_s32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
3060 pData->ap.rssi) ||
3061 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
3062 pData->ap.rtt) ||
3063 nla_put_u32(skb,
3064 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
3065 pData->ap.rtt_sd) ||
3066 nla_put_u16(skb,
3067 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
3068 pData->ap.beaconPeriod) ||
3069 nla_put_u16(skb,
3070 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
3071 pData->ap.capability) ||
3072 nla_put_u32(skb,
3073 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
3074 pData->ieLength))
3075 {
3076 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
3077 goto nla_put_failure;
3078 }
3079 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
3080 pData->ieLength,
3081 pData->ie))
3082 {
3083 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
3084 goto nla_put_failure;
3085 }
3086
3087 cfg80211_vendor_event(skb, GFP_KERNEL);
3088 EXIT();
3089 return;
3090
3091nla_put_failure:
3092 kfree_skb(skb);
3093 return;
3094}
3095
3096static void wlan_hdd_cfg80211_extscan_scan_res_available_event(void *ctx,
3097 void *pMsg)
3098{
3099 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
3100 struct sk_buff *skb = NULL;
3101 tpSirEXTScanResultsAvailableIndParams pData =
3102 (tpSirEXTScanResultsAvailableIndParams) pMsg;
3103
3104 ENTER();
3105
3106 if (wlan_hdd_validate_context(pHddCtx)){
3107 return;
3108 }
3109 if (!pMsg)
3110 {
3111 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
3112 return;
3113 }
3114
3115 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
3116#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
3117 NULL,
3118#endif
3119 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
3120 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
3121 GFP_KERNEL);
3122
3123 if (!skb) {
3124 hddLog(VOS_TRACE_LEVEL_ERROR,
3125 FL("cfg80211_vendor_event_alloc failed"));
3126 return;
3127 }
3128
3129 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
3130 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
3131 hddLog(VOS_TRACE_LEVEL_INFO, "Num results (%u)",
3132 pData->numResultsAvailable);
3133 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
3134 pData->requestId) ||
3135 nla_put_u32(skb,
3136 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
3137 pData->numResultsAvailable)) {
3138 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
3139 goto nla_put_failure;
3140 }
3141
3142 cfg80211_vendor_event(skb, GFP_KERNEL);
3143 EXIT();
3144 return;
3145
3146nla_put_failure:
3147 kfree_skb(skb);
3148 return;
3149}
3150
3151static void wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, void *pMsg)
3152{
3153 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
3154 struct sk_buff *skb = NULL;
3155 tpSirEXTScanProgressIndParams pData =
3156 (tpSirEXTScanProgressIndParams) pMsg;
3157
3158 ENTER();
3159
3160 if (wlan_hdd_validate_context(pHddCtx)){
3161 return;
3162 }
3163 if (!pMsg)
3164 {
3165 hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null"));
3166 return;
3167 }
3168
3169 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
3170#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
3171 NULL,
3172#endif
3173 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
3174 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
3175 GFP_KERNEL);
3176
3177 if (!skb) {
3178 hddLog(VOS_TRACE_LEVEL_ERROR,
3179 FL("cfg80211_vendor_event_alloc failed"));
3180 return;
3181 }
3182 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
3183 hddLog(VOS_TRACE_LEVEL_INFO, "Scan event type (%u)",
3184 pData->extScanEventType);
3185 hddLog(VOS_TRACE_LEVEL_INFO, "Scan event status (%u)",
3186 pData->status);
3187
3188 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
3189 pData->extScanEventType) ||
3190 nla_put_u32(skb,
3191 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
3192 pData->requestId) ||
3193 nla_put_u32(skb,
3194 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_STATUS,
3195 pData->status)) {
3196 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
3197 goto nla_put_failure;
3198 }
3199
3200 cfg80211_vendor_event(skb, GFP_KERNEL);
3201 EXIT();
3202 return;
3203
3204nla_put_failure:
3205 kfree_skb(skb);
3206 return;
3207}
3208
3209void wlan_hdd_cfg80211_extscan_callback(void *ctx, const tANI_U16 evType,
3210 void *pMsg)
3211{
3212 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
3213
3214 ENTER();
3215
3216 if (wlan_hdd_validate_context(pHddCtx)) {
3217 return;
3218 }
3219
3220 hddLog(VOS_TRACE_LEVEL_INFO, FL("Rcvd Event (%d)"), evType);
3221
3222
3223 switch(evType) {
3224 case SIR_HAL_EXTSCAN_START_RSP:
3225 wlan_hdd_cfg80211_extscan_start_rsp(ctx, pMsg);
3226 break;
3227
3228 case SIR_HAL_EXTSCAN_STOP_RSP:
3229 wlan_hdd_cfg80211_extscan_stop_rsp(ctx, pMsg);
3230 break;
3231 case SIR_HAL_EXTSCAN_GET_CACHED_RESULTS_RSP:
3232 /* There is no need to send this response to upper layer
3233 Just log the message */
3234 hddLog(VOS_TRACE_LEVEL_INFO,
3235 FL("Rcvd SIR_HAL_EXTSCAN_CACHED_RESULTS_RSP"));
3236 break;
3237 case SIR_HAL_EXTSCAN_SET_BSS_HOTLIST_RSP:
3238 wlan_hdd_cfg80211_extscan_set_bss_hotlist_rsp(ctx, pMsg);
3239 break;
3240
3241 case SIR_HAL_EXTSCAN_RESET_BSS_HOTLIST_RSP:
3242 wlan_hdd_cfg80211_extscan_reset_bss_hotlist_rsp(ctx, pMsg);
3243 break;
3244
3245 case SIR_HAL_EXTSCAN_SET_SIGNF_RSSI_CHANGE_RSP:
3246 wlan_hdd_cfg80211_extscan_set_signf_wifi_change_rsp(ctx, pMsg);
3247 break;
3248
3249 case SIR_HAL_EXTSCAN_RESET_SIGNF_RSSI_CHANGE_RSP:
3250 wlan_hdd_cfg80211_extscan_reset_signf_wifi_change_rsp(ctx, pMsg);
3251 break;
3252 case SIR_HAL_EXTSCAN_GET_CAPABILITIES_RSP:
3253 wlan_hdd_cfg80211_extscan_get_capabilities_ind(ctx, pMsg);
3254 break;
3255 case SIR_HAL_EXTSCAN_PROGRESS_IND:
3256 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx, pMsg);
3257 break;
3258 case SIR_HAL_EXTSCAN_SCAN_AVAILABLE_IND:
3259 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx, pMsg);
3260 break;
3261 case SIR_HAL_EXTSCAN_SCAN_RESULT_IND:
3262 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
3263 break;
3264 case SIR_HAL_EXTSCAN_HOTLIST_MATCH_IND:
3265 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
3266 break;
3267 case SIR_HAL_EXTSCAN_SIGNF_WIFI_CHANGE_IND:
3268 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx, pMsg);
3269 break;
3270 case SIR_HAL_EXTSCAN_FULL_SCAN_RESULT_IND:
3271 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx, pMsg);
3272 break;
3273 default:
3274 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid event type %d "), evType);
3275 break;
3276 }
3277 EXIT();
3278}
3279
3280static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
3281 struct wireless_dev *wdev,
3282 const void *data, int dataLen)
3283{
3284 tSirGetEXTScanCapabilitiesReqParams reqMsg;
3285 struct net_device *dev = wdev->netdev;
3286 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3287 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3288 struct nlattr
3289 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3290 eHalStatus status;
3291
3292 ENTER();
3293
3294 status = wlan_hdd_validate_context(pHddCtx);
3295 if (0 != status)
3296 {
3297 return -EINVAL;
3298 }
3299 /* check the EXTScan Capability */
3300 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3301 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3302 {
3303 hddLog(VOS_TRACE_LEVEL_ERROR,
3304 FL("EXTScan not enabled/supported by Firmware"));
3305 return -EINVAL;
3306 }
3307
3308 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3309 data, dataLen,
3310 wlan_hdd_extscan_config_policy)) {
3311 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3312 return -EINVAL;
3313 }
3314
3315 /* Parse and fetch request Id */
3316 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3317 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3318 return -EINVAL;
3319 }
3320
3321
3322 reqMsg.requestId = nla_get_u32(
3323 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3324 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
3325
3326 reqMsg.sessionId = pAdapter->sessionId;
3327 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
3328
3329 status = sme_EXTScanGetCapabilities(pHddCtx->hHal, &reqMsg);
3330 if (!HAL_STATUS_SUCCESS(status)) {
3331 hddLog(VOS_TRACE_LEVEL_ERROR,
3332 FL("sme_EXTScanGetCapabilities failed(err=%d)"), status);
3333 return -EINVAL;
3334 }
3335 EXIT();
3336 return 0;
3337}
3338
3339static int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
3340 struct wireless_dev *wdev,
3341 const void *data, int dataLen)
3342{
3343 int ret = 0;
3344
3345 vos_ssr_protect(__func__);
3346 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data, dataLen);
3347 vos_ssr_unprotect(__func__);
3348
3349 return ret;
3350}
3351
3352static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
3353 struct wireless_dev *wdev,
3354 const void *data, int dataLen)
3355{
3356 tSirEXTScanGetCachedResultsReqParams reqMsg;
3357 struct net_device *dev = wdev->netdev;
3358 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3359 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3360 struct nlattr
3361 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3362 eHalStatus status;
3363
3364 ENTER();
3365
3366 status = wlan_hdd_validate_context(pHddCtx);
3367 if (0 != status)
3368 {
3369 return -EINVAL;
3370 }
3371 /* check the EXTScan Capability */
3372 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3373 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3374 {
3375 hddLog(VOS_TRACE_LEVEL_ERROR,
3376 FL("EXTScan not enabled/supported by Firmware"));
3377 return -EINVAL;
3378 }
3379
3380 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3381 data, dataLen,
3382 wlan_hdd_extscan_config_policy)) {
3383 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3384 return -EINVAL;
3385 }
3386 /* Parse and fetch request Id */
3387 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3388 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3389 return -EINVAL;
3390 }
3391
3392 reqMsg.requestId = nla_get_u32(
3393 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3394
3395 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
3396
3397 reqMsg.sessionId = pAdapter->sessionId;
3398 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
3399
3400 /* Parse and fetch flush parameter */
3401 if (!tb
3402 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH])
3403 {
3404 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr flush failed"));
3405 goto failed;
3406 }
3407 reqMsg.flush = nla_get_u8(
3408 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH]);
3409
3410 hddLog(VOS_TRACE_LEVEL_INFO, FL("Flush (%d)"), reqMsg.flush);
3411
3412 status = sme_getCachedResults(pHddCtx->hHal, &reqMsg);
3413 if (!HAL_STATUS_SUCCESS(status)) {
3414 hddLog(VOS_TRACE_LEVEL_ERROR,
3415 FL("sme_getCachedResults failed(err=%d)"), status);
3416 return -EINVAL;
3417 }
3418 EXIT();
3419 return 0;
3420
3421failed:
3422 return -EINVAL;
3423}
3424static int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
3425 struct wireless_dev *wdev,
3426 const void *data, int dataLen)
3427{
3428 int ret = 0;
3429
3430 vos_ssr_protect(__func__);
3431 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data, dataLen);
3432 vos_ssr_unprotect(__func__);
3433
3434 return ret;
3435}
3436
3437static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
3438 struct wireless_dev *wdev,
3439 const void *data, int dataLen)
3440{
3441 tpSirEXTScanSetBssidHotListReqParams pReqMsg = NULL;
3442 struct net_device *dev = wdev->netdev;
3443 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3444 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3445 struct nlattr
3446 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3447 struct nlattr
3448 *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3449 struct nlattr *apTh;
3450 eHalStatus status;
3451 tANI_U8 i = 0;
3452 int rem;
3453
3454 ENTER();
3455
3456 status = wlan_hdd_validate_context(pHddCtx);
3457 if (0 != status)
3458 {
3459 return -EINVAL;
3460 }
3461 /* check the EXTScan Capability */
3462 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3463 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3464 {
3465 hddLog(VOS_TRACE_LEVEL_ERROR,
3466 FL("EXTScan not enabled/supported by Firmware"));
3467 return -EINVAL;
3468 }
3469
3470 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3471 data, dataLen,
3472 wlan_hdd_extscan_config_policy)) {
3473 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3474 return -EINVAL;
3475 }
3476
3477 /* Parse and fetch request Id */
3478 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3479 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3480 return -EINVAL;
3481 }
3482 pReqMsg = (tpSirEXTScanSetBssidHotListReqParams)
3483 vos_mem_malloc(sizeof(*pReqMsg));
3484 if (!pReqMsg) {
3485 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
3486 return -ENOMEM;
3487 }
3488
3489
3490 pReqMsg->requestId = nla_get_u32(
3491 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3492 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), pReqMsg->requestId);
3493
3494 /* Parse and fetch number of APs */
3495 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
3496 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr number of AP failed"));
3497 goto fail;
3498 }
3499
3500 pReqMsg->sessionId = pAdapter->sessionId;
3501 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), pReqMsg->sessionId);
3502
3503 pReqMsg->numAp = nla_get_u32(
3504 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
3505 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of AP (%d)"), pReqMsg->numAp);
3506
3507 nla_for_each_nested(apTh,
3508 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) {
3509 if(nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3510 nla_data(apTh), nla_len(apTh),
3511 NULL)) {
3512 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3513 goto fail;
3514 }
3515
3516 /* Parse and fetch MAC address */
3517 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
3518 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac address failed"));
3519 goto fail;
3520 }
3521 memcpy(pReqMsg->ap[i].bssid, nla_data(
3522 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]),
3523 sizeof(tSirMacAddr));
3524 hddLog(VOS_TRACE_LEVEL_INFO, FL("BSSID: %pM "), pReqMsg->ap[i].bssid);
3525
3526 /* Parse and fetch low RSSI */
3527 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
3528 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr low RSSI failed"));
3529 goto fail;
3530 }
3531 pReqMsg->ap[i].low = nla_get_s32(
3532 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
3533 hddLog(VOS_TRACE_LEVEL_INFO, FL("RSSI low (%d)"), pReqMsg->ap[i].low);
3534
3535 /* Parse and fetch high RSSI */
3536 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
3537 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr high RSSI failed"));
3538 goto fail;
3539 }
3540 pReqMsg->ap[i].high = nla_get_s32(
3541 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
3542 hddLog(VOS_TRACE_LEVEL_INFO, FL("RSSI High (%d)"),
3543 pReqMsg->ap[i].high);
3544
3545 /* Parse and fetch channel */
3546 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]) {
3547 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
3548 goto fail;
3549 }
3550 pReqMsg->ap[i].channel = nla_get_u32(
3551 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]);
3552 hddLog(VOS_TRACE_LEVEL_INFO,
3553 FL("Channel (%u)"), pReqMsg->ap[i].channel);
3554 i++;
3555 }
3556 status = sme_SetBssHotlist(pHddCtx->hHal, pReqMsg);
3557 if (!HAL_STATUS_SUCCESS(status)) {
3558 hddLog(VOS_TRACE_LEVEL_ERROR,
3559 FL("sme_SetBssHotlist failed(err=%d)"), status);
3560 vos_mem_free(pReqMsg);
3561 return -EINVAL;
3562 }
3563
3564 vos_mem_free(pReqMsg);
3565 EXIT();
3566 return 0;
3567
3568fail:
3569 vos_mem_free(pReqMsg);
3570 return -EINVAL;
3571}
3572
3573static int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
3574 struct wireless_dev *wdev,
3575 const void *data, int dataLen)
3576{
3577 int ret = 0;
3578
3579 vos_ssr_protect(__func__);
3580 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
3581 dataLen);
3582 vos_ssr_unprotect(__func__);
3583
3584 return ret;
3585}
3586
3587static int __wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
3588 struct wireless_dev *wdev,
3589 const void *data, int dataLen)
3590{
3591 tpSirEXTScanSetSignificantChangeReqParams pReqMsg = NULL;
3592 struct net_device *dev = wdev->netdev;
3593 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3594 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3595 struct nlattr
3596 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3597 struct nlattr
3598 *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3599 struct nlattr *apTh;
3600 eHalStatus status;
3601 int i = 0;
3602 int rem;
3603
3604 ENTER();
3605
3606 status = wlan_hdd_validate_context(pHddCtx);
3607 if (0 != status)
3608 {
3609 return -EINVAL;
3610 }
3611 /* check the EXTScan Capability */
3612 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3613 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3614 {
3615 hddLog(VOS_TRACE_LEVEL_ERROR,
3616 FL("EXTScan not enabled/supported by Firmware"));
3617 return -EINVAL;
3618 }
3619
3620 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3621 data, dataLen,
3622 wlan_hdd_extscan_config_policy)) {
3623 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3624 return -EINVAL;
3625 }
3626
3627 /* Parse and fetch request Id */
3628 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3629 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3630 return -EINVAL;
3631 }
3632 pReqMsg = (tpSirEXTScanSetSignificantChangeReqParams)
3633 vos_mem_malloc(sizeof(*pReqMsg));
3634 if (!pReqMsg) {
3635 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
3636 return -ENOMEM;
3637 }
3638
3639
3640
3641 pReqMsg->requestId = nla_get_u32(
3642 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3643 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), pReqMsg->requestId);
3644
3645 /* Parse and fetch RSSI sample size */
3646 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE])
3647 {
3648 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr RSSI sample size failed"));
3649 goto fail;
3650 }
3651 pReqMsg->rssiSampleSize = nla_get_u32(
3652 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
3653 hddLog(VOS_TRACE_LEVEL_INFO,
3654 FL("RSSI sample size (%u)"), pReqMsg->rssiSampleSize);
3655
3656 /* Parse and fetch lost AP sample size */
3657 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE])
3658 {
3659 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr lost AP sample size failed"));
3660 goto fail;
3661 }
3662 pReqMsg->lostApSampleSize = nla_get_u32(
3663 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
3664 hddLog(VOS_TRACE_LEVEL_INFO,
3665 FL("Lost AP sample size (%u)"), pReqMsg->lostApSampleSize);
3666 /* Parse and fetch minimum Breaching */
3667 if (!tb
3668 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
3669 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr minBreaching failed"));
3670 goto fail;
3671 }
3672 pReqMsg->minBreaching = nla_get_u32(
3673 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
3674 hddLog(VOS_TRACE_LEVEL_INFO, FL(" Breaching (%d)"), pReqMsg->minBreaching);
3675
3676 /* Parse and fetch number of APs */
3677 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
3678 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr number of AP failed"));
3679 goto fail;
3680 }
3681 pReqMsg->numAp = nla_get_u32(
3682 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
3683 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of AP (%d)"), pReqMsg->numAp);
3684
3685 pReqMsg->sessionId = pAdapter->sessionId;
3686 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), pReqMsg->sessionId);
3687
3688 nla_for_each_nested(apTh,
3689 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) {
3690 if(nla_parse(tb2,
3691 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3692 nla_data(apTh), nla_len(apTh),
3693 NULL)) {
3694 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3695 goto fail;
3696 }
3697
3698 /* Parse and fetch MAC address */
3699 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
3700 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac address failed"));
3701 goto fail;
3702 }
3703 memcpy(pReqMsg->ap[i].bssid, nla_data(
3704 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]),
3705 sizeof(tSirMacAddr));
3706
3707 /* Parse and fetch low RSSI */
3708 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
3709 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr low RSSI failed"));
3710 goto fail;
3711 }
3712 pReqMsg->ap[i].low = nla_get_s32(
3713 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
3714 hddLog(VOS_TRACE_LEVEL_INFO, FL("RSSI low (%d)"), pReqMsg->ap[i].low);
3715
3716 /* Parse and fetch high RSSI */
3717 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
3718 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr high RSSI failed"));
3719 goto fail;
3720 }
3721 pReqMsg->ap[i].high = nla_get_s32(
3722 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
3723 hddLog(VOS_TRACE_LEVEL_INFO,
3724 FL("RSSI High (%d)"), pReqMsg->ap[i].high);
3725
3726 /* Parse and fetch channel */
3727 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]) {
3728 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
3729 goto fail;
3730 }
3731 pReqMsg->ap[i].channel = nla_get_u32(
3732 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]);
3733 hddLog(VOS_TRACE_LEVEL_INFO,
3734 FL("Channel (%u)"), pReqMsg->ap[i].channel);
3735 i++;
3736 }
3737
3738 status = sme_SetSignificantChange(pHddCtx->hHal, pReqMsg);
3739 if (!HAL_STATUS_SUCCESS(status)) {
3740 hddLog(VOS_TRACE_LEVEL_ERROR,
3741 FL("sme_SetSignificantChange failed(err=%d)"), status);
3742 vos_mem_free(pReqMsg);
3743 return -EINVAL;
3744 }
3745 vos_mem_free(pReqMsg);
3746 EXIT();
3747 return 0;
3748
3749fail:
3750 vos_mem_free(pReqMsg);
3751 return -EINVAL;
3752}
3753
3754static int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
3755 struct wireless_dev *wdev,
3756 const void *data, int dataLen)
3757{
3758 int ret = 0;
3759
3760 vos_ssr_protect(__func__);
3761 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev, data,
3762 dataLen);
3763 vos_ssr_unprotect(__func__);
3764
3765 return ret;
3766}
3767
3768static int __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
3769 struct wireless_dev *wdev,
3770 const void *data, int dataLen)
3771{
3772 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3773 tANI_U32 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3774 tANI_U8 numChannels = 0;
3775 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3776 tANI_U32 requestId;
3777 tWifiBand wifiBand;
3778 eHalStatus status;
3779 struct sk_buff *replySkb;
3780 tANI_U8 i;
3781 int ret;
3782
3783 ENTER();
3784
3785 status = wlan_hdd_validate_context(pHddCtx);
3786 if (0 != status)
3787 {
3788 return -EINVAL;
3789 }
3790
3791 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3792 data, dataLen,
3793 wlan_hdd_extscan_config_policy)) {
3794 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3795 return -EINVAL;
3796 }
3797
3798 /* Parse and fetch request Id */
3799 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3800 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3801 return -EINVAL;
3802 }
3803 requestId = nla_get_u32(
3804 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3805 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), requestId);
3806
3807 /* Parse and fetch wifi band */
3808 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND])
3809 {
3810 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr wifi band failed"));
3811 return -EINVAL;
3812 }
3813 wifiBand = nla_get_u32(
3814 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
3815 hddLog(VOS_TRACE_LEVEL_INFO, FL("Wifi band (%d)"), wifiBand);
3816
3817 status = sme_GetValidChannelsByBand((tHalHandle)(pHddCtx->hHal),
3818 wifiBand, ChannelList,
3819 &numChannels);
3820 if (eHAL_STATUS_SUCCESS != status) {
3821 hddLog(VOS_TRACE_LEVEL_ERROR,
3822 FL("sme_GetValidChannelsByBand failed (err=%d)"), status);
3823 return -EINVAL;
3824 }
3825 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of channels (%d)"), numChannels);
3826 for (i = 0; i < numChannels; i++)
3827 hddLog(VOS_TRACE_LEVEL_INFO, "Channel: %u ", ChannelList[i]);
3828
3829 replySkb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
3830 sizeof(u32) * numChannels +
3831 NLMSG_HDRLEN);
3832
3833 if (!replySkb) {
3834 hddLog(VOS_TRACE_LEVEL_ERROR,
3835 FL("valid channels: buffer alloc fail"));
3836 return -EINVAL;
3837 }
3838 if (nla_put_u32(replySkb,
3839 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
3840 numChannels) ||
3841 nla_put(replySkb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
3842 sizeof(u32) * numChannels, ChannelList)) {
3843
3844 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
3845 kfree_skb(replySkb);
3846 return -EINVAL;
3847 }
3848
3849 ret = cfg80211_vendor_cmd_reply(replySkb);
3850
3851 EXIT();
3852 return ret;
3853}
3854
3855static int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
3856 struct wireless_dev *wdev,
3857 const void *data, int dataLen)
3858{
3859 int ret = 0;
3860
3861 vos_ssr_protect(__func__);
3862 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
3863 dataLen);
3864 vos_ssr_unprotect(__func__);
3865
3866 return ret;
3867}
3868
3869static int __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3870 struct wireless_dev *wdev,
3871 const void *data, int dataLen)
3872{
3873 tpSirEXTScanStartReqParams pReqMsg = NULL;
3874 struct net_device *dev = wdev->netdev;
3875 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3876 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3877 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3878 struct nlattr *bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3879 struct nlattr *channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3880 struct nlattr *buckets;
3881 struct nlattr *channels;
3882 int rem1;
3883 int rem2;
3884 eHalStatus status;
3885 tANI_U32 j = 0, index = 0;
3886
3887 ENTER();
3888
3889 status = wlan_hdd_validate_context(pHddCtx);
3890 if (0 != status)
3891 {
3892 return -EINVAL;
3893 }
3894 /* check the EXTScan Capability */
3895 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3896 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3897 {
3898 hddLog(VOS_TRACE_LEVEL_ERROR,
3899 FL("EXTScan not enabled/supported by Firmware"));
3900 return -EINVAL;
3901 }
3902
3903 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3904 data, dataLen,
3905 wlan_hdd_extscan_config_policy)) {
3906 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3907 return -EINVAL;
3908 }
3909
3910 /* Parse and fetch request Id */
3911 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3912 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3913 return -EINVAL;
3914 }
3915
3916 pReqMsg = (tpSirEXTScanStartReqParams)
3917 vos_mem_malloc(sizeof(*pReqMsg));
3918 if (!pReqMsg) {
3919 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
3920 return -ENOMEM;
3921 }
3922
3923 pReqMsg->requestId = nla_get_u32(
3924 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3925 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), pReqMsg->requestId);
3926
3927 pReqMsg->sessionId = pAdapter->sessionId;
3928 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), pReqMsg->sessionId);
3929
3930 /* Parse and fetch base period */
3931 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD]) {
3932 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr base period failed"));
3933 goto fail;
3934 }
3935 pReqMsg->basePeriod = nla_get_u32(
3936 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD]);
3937 hddLog(VOS_TRACE_LEVEL_INFO, FL("Base Period (%d)"),
3938 pReqMsg->basePeriod);
3939
3940 /* Parse and fetch max AP per scan */
3941 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN]) {
3942 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr max_ap_per_scan failed"));
3943 goto fail;
3944 }
3945 pReqMsg->maxAPperScan = nla_get_u32(
3946 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN]);
3947 hddLog(VOS_TRACE_LEVEL_INFO, FL("Max AP per Scan (%d)"),
3948 pReqMsg->maxAPperScan);
3949
3950 /* Parse and fetch report threshold */
3951 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD]) {
3952 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr report_threshold failed"));
3953 goto fail;
3954 }
3955 pReqMsg->reportThreshold = nla_get_u8(
3956 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD]);
3957 hddLog(VOS_TRACE_LEVEL_INFO, FL("Report Threshold (%d)"),
3958 pReqMsg->reportThreshold);
3959
3960 /* Parse and fetch number of buckets */
3961 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS]) {
3962 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr number of buckets failed"));
3963 goto fail;
3964 }
3965 pReqMsg->numBuckets = nla_get_u8(
3966 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS]);
3967 if (pReqMsg->numBuckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3968 hddLog(VOS_TRACE_LEVEL_WARN, FL("Exceeded MAX number of buckets "
3969 "Setting numBuckets to %u"), WLAN_EXTSCAN_MAX_BUCKETS);
3970 pReqMsg->numBuckets = WLAN_EXTSCAN_MAX_BUCKETS;
3971 }
3972 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of Buckets (%d)"),
3973 pReqMsg->numBuckets);
3974 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
3975 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bucket spec failed"));
3976 goto fail;
3977 }
3978
3979 nla_for_each_nested(buckets,
3980 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
3981 if(nla_parse(bucket,
3982 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3983 nla_data(buckets), nla_len(buckets), NULL)) { //policy
3984 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3985 goto fail;
3986 }
3987
3988 /* Parse and fetch bucket spec */
3989 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
3990 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bucket index failed"));
3991 goto fail;
3992 }
3993
3994 pReqMsg->buckets[index].bucket = nla_get_u8(
3995 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
3996
3997 hddLog(VOS_TRACE_LEVEL_INFO, FL("Bucket spec Index (%d)"),
3998 pReqMsg->buckets[index].bucket);
3999
4000 /* Parse and fetch wifi band */
4001 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
4002 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr wifi band failed"));
4003 goto fail;
4004 }
4005 pReqMsg->buckets[index].band = nla_get_u8(
4006 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
4007 hddLog(VOS_TRACE_LEVEL_INFO, FL("Wifi band (%d)"),
4008 pReqMsg->buckets[index].band);
4009
4010 /* Parse and fetch period */
4011 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
4012 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr period failed"));
4013 goto fail;
4014 }
4015 pReqMsg->buckets[index].period = nla_get_u32(
4016 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
4017 hddLog(VOS_TRACE_LEVEL_INFO, FL("period (%d)"),
4018 pReqMsg->buckets[index].period);
4019
4020 /* Parse and fetch report events */
4021 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
4022 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr report events failed"));
4023 goto fail;
4024 }
4025 pReqMsg->buckets[index].reportEvents = nla_get_u8(
4026 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
4027 hddLog(VOS_TRACE_LEVEL_INFO, FL("report events (%d)"),
4028 pReqMsg->buckets[index].reportEvents);
4029
4030 /* Parse and fetch number of channels */
4031 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS])
4032 {
4033 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr num channels failed"));
4034 goto fail;
4035 }
4036 pReqMsg->buckets[index].numChannels = nla_get_u32(
4037 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
4038 hddLog(VOS_TRACE_LEVEL_INFO, FL("num channels (%d)"),
4039 pReqMsg->buckets[index].numChannels);
4040
4041 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
4042 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel spec failed"));
4043 goto fail;
4044 }
4045
4046 j = 0;
4047 nla_for_each_nested(channels,
4048 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
4049 if(nla_parse(channel,
4050 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
4051 nla_data(channels), nla_len(channels),
4052 NULL)) { //wlan_hdd_extscan_config_policy here
4053 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
4054 goto fail;
4055 }
4056
4057 /* Parse and fetch channel */
4058 if (!channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
4059 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
4060 goto fail;
4061 }
4062 pReqMsg->buckets[index].channels[j].channel = nla_get_u32(
4063 channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
4064 hddLog(VOS_TRACE_LEVEL_INFO, FL("channel (%u)"),
4065 pReqMsg->buckets[index].channels[j].channel);
4066
4067 /* Parse and fetch dwell time */
4068 if (!channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
4069 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr dwelltime failed"));
4070 goto fail;
4071 }
4072 pReqMsg->buckets[index].channels[j].dwellTimeMs = nla_get_u32(
4073 channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
4074 hddLog(VOS_TRACE_LEVEL_INFO, FL("Dwell time (%u ms)"),
4075 pReqMsg->buckets[index].channels[j].dwellTimeMs);
4076
4077 /* Parse and fetch channel spec passive */
4078 if (!channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
4079 hddLog(VOS_TRACE_LEVEL_ERROR,
4080 FL("attr channel spec passive failed"));
4081 goto fail;
4082 }
4083 pReqMsg->buckets[index].channels[j].passive = nla_get_u8(
4084 channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
4085 hddLog(VOS_TRACE_LEVEL_INFO, FL("Chnl spec passive (%u)"),
4086 pReqMsg->buckets[index].channels[j].passive);
4087 j++;
4088 }
4089 index++;
4090 }
4091 status = sme_EXTScanStart(pHddCtx->hHal, pReqMsg);
4092 if (!HAL_STATUS_SUCCESS(status)) {
4093 hddLog(VOS_TRACE_LEVEL_ERROR,
4094 FL("sme_EXTScanStart failed(err=%d)"), status);
4095 vos_mem_free(pReqMsg);
4096 return -EINVAL;
4097 }
4098
4099 vos_mem_free(pReqMsg);
4100 EXIT();
4101 return 0;
4102
4103fail:
4104 vos_mem_free(pReqMsg);
4105 return -EINVAL;
4106}
4107
4108static int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
4109 struct wireless_dev *wdev,
4110 const void *data, int dataLen)
4111{
4112 int ret = 0;
4113
4114 vos_ssr_protect(__func__);
4115 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, dataLen);
4116 vos_ssr_unprotect(__func__);
4117
4118 return ret;
4119}
4120
4121static int __wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
4122 struct wireless_dev *wdev,
4123 const void *data, int dataLen)
4124{
4125 tSirEXTScanStopReqParams reqMsg;
4126 struct net_device *dev = wdev->netdev;
4127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4128 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4129 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
4130 eHalStatus status;
4131
4132 ENTER();
4133
4134 status = wlan_hdd_validate_context(pHddCtx);
4135 if (0 != status)
4136 {
4137 return -EINVAL;
4138 }
4139 /* check the EXTScan Capability */
4140 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
4141 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
4142 {
4143 hddLog(VOS_TRACE_LEVEL_ERROR,
4144 FL("EXTScan not enabled/supported by Firmware"));
4145 return -EINVAL;
4146 }
4147
4148 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
4149 data, dataLen,
4150 wlan_hdd_extscan_config_policy)) {
4151 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4152 return -EINVAL;
4153 }
4154
4155 /* Parse and fetch request Id */
4156 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
4157 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
4158 return -EINVAL;
4159 }
4160
4161 reqMsg.requestId = nla_get_u32(
4162 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4163 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
4164
4165 reqMsg.sessionId = pAdapter->sessionId;
4166 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
4167
4168 status = sme_EXTScanStop(pHddCtx->hHal, &reqMsg);
4169 if (!HAL_STATUS_SUCCESS(status)) {
4170 hddLog(VOS_TRACE_LEVEL_ERROR,
4171 FL("sme_EXTScanStop failed(err=%d)"), status);
4172 return -EINVAL;
4173 }
4174
4175 EXIT();
4176 return 0;
4177}
4178
4179static int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
4180 struct wireless_dev *wdev,
4181 const void *data, int dataLen)
4182{
4183 int ret = 0;
4184
4185 vos_ssr_protect(__func__);
4186 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, dataLen);
4187 vos_ssr_unprotect(__func__);
4188
4189 return ret;
4190}
4191
4192static int __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
4193 struct wireless_dev *wdev,
4194 const void *data, int dataLen)
4195{
4196 tSirEXTScanResetBssidHotlistReqParams reqMsg;
4197 struct net_device *dev = wdev->netdev;
4198 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4199 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4200 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
4201 eHalStatus status;
4202
4203 ENTER();
4204
4205 status = wlan_hdd_validate_context(pHddCtx);
4206 if (0 != status)
4207 {
4208 return -EINVAL;
4209 }
4210 /* check the EXTScan Capability */
4211 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
4212 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
4213 {
4214 hddLog(VOS_TRACE_LEVEL_ERROR,
4215 FL("EXTScan not enabled/supported by Firmware"));
4216 return -EINVAL;
4217 }
4218
4219 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
4220 data, dataLen,
4221 wlan_hdd_extscan_config_policy)) {
4222 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4223 return -EINVAL;
4224 }
4225
4226 /* Parse and fetch request Id */
4227 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
4228 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
4229 return -EINVAL;
4230 }
4231
4232 reqMsg.requestId = nla_get_u32(
4233 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4234 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
4235
4236 reqMsg.sessionId = pAdapter->sessionId;
4237 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
4238
4239 status = sme_ResetBssHotlist(pHddCtx->hHal, &reqMsg);
4240 if (!HAL_STATUS_SUCCESS(status)) {
4241 hddLog(VOS_TRACE_LEVEL_ERROR,
4242 FL("sme_ResetBssHotlist failed(err=%d)"), status);
4243 return -EINVAL;
4244 }
4245 EXIT();
4246 return 0;
4247}
4248
4249static int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
4250 struct wireless_dev *wdev,
4251 const void *data, int dataLen)
4252{
4253 int ret = 0;
4254
4255 vos_ssr_protect(__func__);
4256 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev, data, dataLen);
4257 vos_ssr_unprotect(__func__);
4258
4259 return ret;
4260}
4261
4262static int __wlan_hdd_cfg80211_extscan_reset_significant_change(
4263 struct wiphy *wiphy,
4264 struct wireless_dev *wdev,
4265 const void *data, int dataLen)
4266{
4267 tSirEXTScanResetSignificantChangeReqParams reqMsg;
4268 struct net_device *dev = wdev->netdev;
4269 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4270 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4271 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
4272 eHalStatus status;
4273
4274 ENTER();
4275
4276 status = wlan_hdd_validate_context(pHddCtx);
4277 if (0 != status)
4278 {
4279 return -EINVAL;
4280 }
4281 /* check the EXTScan Capability */
4282 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
4283 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
4284 {
4285 hddLog(VOS_TRACE_LEVEL_ERROR,
4286 FL("EXTScan not enabled/supported by Firmware"));
4287 return -EINVAL;
4288 }
4289
4290 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
4291 data, dataLen,
4292 wlan_hdd_extscan_config_policy)) {
4293 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4294 return -EINVAL;
4295 }
4296
4297 /* Parse and fetch request Id */
4298 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
4299 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
4300 return -EINVAL;
4301 }
4302
4303
4304 reqMsg.requestId = nla_get_u32(
4305 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4306 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
4307
4308 reqMsg.sessionId = pAdapter->sessionId;
4309 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
4310
4311 status = sme_ResetSignificantChange(pHddCtx->hHal, &reqMsg);
4312 if (!HAL_STATUS_SUCCESS(status)) {
4313 hddLog(VOS_TRACE_LEVEL_ERROR,
4314 FL("sme_ResetSignificantChange failed(err=%d)"), status);
4315 return -EINVAL;
4316 }
4317
4318 EXIT();
4319 return 0;
4320}
4321
4322static int wlan_hdd_cfg80211_extscan_reset_significant_change(
4323 struct wiphy *wiphy,
4324 struct wireless_dev *wdev,
4325 const void *data, int dataLen)
4326{
4327 int ret = 0;
4328
4329 vos_ssr_protect(__func__);
4330 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy,
4331 wdev, data,
4332 dataLen);
4333 vos_ssr_unprotect(__func__);
4334
4335 return ret;
4336}
4337#endif /* WLAN_FEATURE_EXTSCAN */
4338
4339/*EXT TDLS*/
4340static const struct nla_policy
4341wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] =
4342{
4343 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC },
4344 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_S32 },
4345 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] =
4346 {.type = NLA_S32 },
4347 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_S32 },
4348 [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type = NLA_S32 },
4349
4350};
4351
4352static const struct nla_policy
4353wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +1] =
4354{
4355 [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {.type = NLA_UNSPEC },
4356
4357};
4358
4359static const struct nla_policy
4360wlan_hdd_tdls_config_state_change_policy[
4361 QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX +1] =
4362{
4363 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {.type = NLA_UNSPEC },
4364 [QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_S32 },
4365 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32 },
4366 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_S32 },
4367 [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS] =
4368 {.type = NLA_S32 },
4369
4370};
4371
4372static const struct nla_policy
4373wlan_hdd_tdls_config_get_status_policy[
4374 QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX +1] =
4375{
4376 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {.type = NLA_UNSPEC },
4377 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_S32 },
4378 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32 },
4379 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_S32 },
4380 [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS]
4381 = {.type = NLA_S32 },
4382
4383};
4384
4385static const struct nla_policy
4386wlan_hdd_mac_config[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX+1] =
4387{
4388 [QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI] = {.type = NLA_UNSPEC },
4389};
4390
4391static int __wlan_hdd_cfg80211_set_spoofed_mac_oui(struct wiphy *wiphy,
4392 struct wireless_dev *wdev,
4393 const void *data,
4394 int data_len)
4395{
4396
4397 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4398 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
4399
4400 ENTER();
4401
4402 if (0 != wlan_hdd_validate_context(pHddCtx)){
4403 return -EINVAL;
4404 }
4405 if (0 == pHddCtx->cfg_ini->enableMacSpoofing) {
4406 hddLog(VOS_TRACE_LEVEL_INFO, FL("MAC_SPOOFED_SCAN disabled in ini"));
4407 return -ENOTSUPP;
4408 }
4409 if (TRUE != sme_IsFeatureSupportedByFW(MAC_SPOOFED_SCAN)){
4410 hddLog(VOS_TRACE_LEVEL_INFO, FL("MAC_SPOOFED_SCAN not supported by FW"));
4411 return -ENOTSUPP;
4412 }
4413
4414 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
4415 data, data_len, wlan_hdd_mac_config)) {
4416 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4417 return -EINVAL;
4418 }
4419
4420 /* Parse and fetch mac address */
4421 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
4422 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed"));
4423 return -EINVAL;
4424 }
4425
4426 memcpy(pHddCtx->spoofMacAddr.randomMacAddr.bytes, nla_data(
4427 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]),
4428 VOS_MAC_ADDR_LAST_3_BYTES);
4429
4430 pHddCtx->spoofMacAddr.isEnabled = TRUE;
4431
4432 vos_trace_hex_dump( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, nla_data(
4433 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]),
4434 VOS_MAC_ADDR_FIRST_3_BYTES);
4435 if ((pHddCtx->spoofMacAddr.randomMacAddr.bytes[0] == 0) &&
4436 (pHddCtx->spoofMacAddr.randomMacAddr.bytes[1] == 0) &&
4437 (pHddCtx->spoofMacAddr.randomMacAddr.bytes[2] == 0))
4438 {
4439 hddLog(LOG1, FL("ZERO MAC OUI Recieved. Disabling Spoofing"));
4440 vos_mem_zero(pHddCtx->spoofMacAddr.randomMacAddr.bytes,
4441 VOS_MAC_ADDRESS_LEN);
4442 pHddCtx->spoofMacAddr.isEnabled = FALSE;
4443 }
4444
4445 if (VOS_STATUS_SUCCESS != hdd_processSpoofMacAddrRequest(pHddCtx))
4446 {
4447 hddLog(LOGE, FL("Failed to send Spoof Mac Addr to FW"));
4448 }
4449
4450 EXIT();
4451 return 0;
4452}
4453
4454static int wlan_hdd_cfg80211_set_spoofed_mac_oui(struct wiphy *wiphy,
4455 struct wireless_dev *wdev,
4456 const void *data,
4457 int data_len)
4458{
4459 int ret = 0;
4460
4461 vos_ssr_protect(__func__);
4462 ret = __wlan_hdd_cfg80211_set_spoofed_mac_oui(wiphy, wdev, data, data_len);
4463 vos_ssr_unprotect(__func__);
4464
4465 return ret;
4466}
4467
4468static int __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
4469 struct wireless_dev *wdev,
4470 const void *data,
4471 int data_len)
4472{
4473 u8 peer[6] = {0};
4474 struct net_device *dev = wdev->netdev;
4475 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4476 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4477 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX + 1];
4478 eHalStatus ret;
4479 tANI_S32 state;
4480 tANI_S32 reason;
4481 tANI_S32 global_operating_class = 0;
4482 tANI_S32 channel = 0;
4483 struct sk_buff *skb = NULL;
4484 int retVal;
4485
4486 ENTER();
4487
4488 if (!pAdapter) {
4489 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adpater is NULL"));
4490 return -EINVAL;
4491 }
4492
4493 ret = wlan_hdd_validate_context(pHddCtx);
4494 if (0 != ret) {
4495 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid HDD context"));
4496 return -EINVAL;
4497 }
4498 if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) {
4499 hddLog(VOS_TRACE_LEVEL_ERROR, FL("TDLS external control is disabled"));
4500 return -ENOTSUPP;
4501 }
4502 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX,
4503 data, data_len,
4504 wlan_hdd_tdls_config_get_status_policy)) {
4505 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4506 return -EINVAL;
4507 }
4508
4509 /* Parse and fetch mac address */
4510 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]) {
4511 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed"));
4512 return -EINVAL;
4513 }
4514
4515 memcpy(peer, nla_data(
4516 tb[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR]),
4517 sizeof(peer));
4518 hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer));
4519
4520 wlan_hdd_tdls_get_status(pAdapter, peer, &state, &reason);
4521
4522 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4523 4 * sizeof(s32) +
4524 NLMSG_HDRLEN);
4525
4526 if (!skb) {
4527 hddLog(VOS_TRACE_LEVEL_ERROR,
4528 FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
4529 return -EINVAL;
4530 }
4531 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reason (%d) Status (%d) class (%d) channel (%d) peer" MAC_ADDRESS_STR),
4532 reason,
4533 state,
4534 global_operating_class,
4535 channel,
4536 MAC_ADDR_ARRAY(peer));
4537 if (nla_put_s32(skb,
4538 QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE,
4539 state) ||
4540 nla_put_s32(skb,
4541 QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON,
4542 reason) ||
4543 nla_put_s32(skb,
4544 QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS,
4545 global_operating_class) ||
4546 nla_put_s32(skb,
4547 QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL,
4548 channel)) {
4549
4550 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
4551 goto nla_put_failure;
4552 }
4553
4554 retVal = cfg80211_vendor_cmd_reply(skb);
4555 EXIT();
4556 return retVal;
4557
4558nla_put_failure:
4559 kfree_skb(skb);
4560 return -EINVAL;
4561}
4562
4563static int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
4564 struct wireless_dev *wdev,
4565 const void *data,
4566 int data_len)
4567{
4568 int ret = 0;
4569
4570 vos_ssr_protect(__func__);
4571 ret = __wlan_hdd_cfg80211_exttdls_get_status(wiphy, wdev, data, data_len);
4572 vos_ssr_unprotect(__func__);
4573
4574 return ret;
4575}
4576
4577static int wlan_hdd_cfg80211_exttdls_callback(
4578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
4579 const tANI_U8* mac,
4580#else
4581 tANI_U8* mac,
4582#endif
4583 tANI_S32 state,
4584 tANI_S32 reason,
4585 void *ctx)
4586{
4587 hdd_adapter_t* pAdapter = (hdd_adapter_t*)ctx;
4588 struct sk_buff *skb = NULL;
4589 tANI_S32 global_operating_class = 0;
4590 tANI_S32 channel = 0;
4591 hdd_context_t *pHddCtx;
4592
4593 ENTER();
4594
4595 if (!pAdapter) {
4596 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adpater is NULL"));
4597 return -EINVAL;
4598 }
4599
4600 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4601 if (wlan_hdd_validate_context(pHddCtx)) {
4602 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid HDD context"));
4603 return -EINVAL;
4604 }
4605
4606 if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) {
4607 hddLog(VOS_TRACE_LEVEL_ERROR, FL("TDLS external control is disabled"));
4608 return -ENOTSUPP;
4609 }
4610 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
4611#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
4612 NULL,
4613#endif
4614 EXTTDLS_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4615 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX,
4616 GFP_KERNEL);
4617
4618 if (!skb) {
4619 hddLog(VOS_TRACE_LEVEL_ERROR,
4620 FL("cfg80211_vendor_event_alloc failed"));
4621 return -EINVAL;
4622 }
4623 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
4624 hddLog(VOS_TRACE_LEVEL_INFO, "Reason: (%d) Status: (%d) Class: (%d) Channel: (%d)",
4625 reason,
4626 state,
4627 global_operating_class,
4628 channel);
4629 hddLog(VOS_TRACE_LEVEL_WARN, "tdls peer " MAC_ADDRESS_STR,
4630 MAC_ADDR_ARRAY(mac));
4631
4632 if (nla_put(skb,
4633 QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR,
4634 VOS_MAC_ADDR_SIZE, mac) ||
4635 nla_put_s32(skb,
4636 QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE,
4637 state) ||
4638 nla_put_s32(skb,
4639 QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON,
4640 reason) ||
4641 nla_put_s32(skb,
4642 QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL,
4643 channel) ||
4644 nla_put_s32(skb,
4645 QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS,
4646 global_operating_class)
4647 ) {
4648 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
4649 goto nla_put_failure;
4650 }
4651
4652 cfg80211_vendor_event(skb, GFP_KERNEL);
4653 EXIT();
4654 return (0);
4655
4656nla_put_failure:
4657 kfree_skb(skb);
4658 return -EINVAL;
4659}
4660
4661static int __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
4662 struct wireless_dev *wdev,
4663 const void *data,
4664 int data_len)
4665{
4666 u8 peer[6] = {0};
4667 struct net_device *dev = wdev->netdev;
4668 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4669 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX + 1];
4670 eHalStatus status;
4671 tdls_req_params_t pReqMsg = {0};
4672 int ret;
4673 hdd_adapter_t *pAdapter;
4674
4675 ENTER();
4676
4677 if (!dev) {
4678 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Dev pointer is NULL"));
4679 return -EINVAL;
4680 }
4681
4682 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4683 if (!pAdapter) {
4684 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adpater is NULL"));
4685 return -EINVAL;
4686 }
4687
4688 status = wlan_hdd_validate_context(pHddCtx);
4689 if (0 != status) {
4690 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid HDD context"));
4691 return -EINVAL;
4692 }
4693 if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) {
4694 hddLog(VOS_TRACE_LEVEL_ERROR, FL("TDLS external control is disabled"));
4695 return -ENOTSUPP;
4696 }
4697 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX,
4698 data, data_len,
4699 wlan_hdd_tdls_config_enable_policy)) {
4700 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4701 return -EINVAL;
4702 }
4703
4704 /* Parse and fetch mac address */
4705 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]) {
4706 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed"));
4707 return -EINVAL;
4708 }
4709
4710 memcpy(peer, nla_data(
4711 tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR]),
4712 sizeof(peer));
4713 hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer));
4714
4715 /* Parse and fetch channel */
4716 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]) {
4717 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
4718 return -EINVAL;
4719 }
4720 pReqMsg.channel = nla_get_s32(
4721 tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL]);
4722 hddLog(VOS_TRACE_LEVEL_INFO, FL("Channel Num (%d)"), pReqMsg.channel);
4723
4724 /* Parse and fetch global operating class */
4725 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]) {
4726 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr operating class failed"));
4727 return -EINVAL;
4728 }
4729 pReqMsg.global_operating_class = nla_get_s32(
4730 tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS]);
4731 hddLog(VOS_TRACE_LEVEL_INFO, FL("Operating class (%d)"),
4732 pReqMsg.global_operating_class);
4733
4734 /* Parse and fetch latency ms */
4735 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]) {
4736 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr latency failed"));
4737 return -EINVAL;
4738 }
4739 pReqMsg.max_latency_ms = nla_get_s32(
4740 tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS]);
4741 hddLog(VOS_TRACE_LEVEL_INFO, FL("Latency (%d)"),
4742 pReqMsg.max_latency_ms);
4743
4744 /* Parse and fetch required bandwidth kbps */
4745 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]) {
4746 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bandwidth failed"));
4747 return -EINVAL;
4748 }
4749
4750 pReqMsg.min_bandwidth_kbps = nla_get_s32(
4751 tb[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS]);
4752 hddLog(VOS_TRACE_LEVEL_INFO, FL("Bandwidth (%d)"),
4753 pReqMsg.min_bandwidth_kbps);
4754
4755 ret = wlan_hdd_tdls_extctrl_config_peer(pAdapter,
4756 peer,
4757 &pReqMsg,
4758 wlan_hdd_cfg80211_exttdls_callback);
4759
4760 EXIT();
4761 return ret;
4762}
4763
4764static int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
4765 struct wireless_dev *wdev,
4766 const void *data,
4767 int data_len)
4768{
4769 int ret = 0;
4770
4771 vos_ssr_protect(__func__);
4772 ret = __wlan_hdd_cfg80211_exttdls_enable(wiphy, wdev, data, data_len);
4773 vos_ssr_unprotect(__func__);
4774
4775 return ret;
4776}
4777
4778static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
4779 struct wireless_dev *wdev,
4780 const void *data,
4781 int data_len)
4782{
4783 u8 peer[6] = {0};
4784 struct net_device *dev = wdev->netdev;
4785 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4786 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX + 1];
4787 eHalStatus status;
4788 int ret;
4789 hdd_adapter_t *pAdapter;
4790
4791 ENTER();
4792
4793 if (!dev) {
4794 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Dev pointer is NULL"));
4795 return -EINVAL;
4796 }
4797
4798 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4799 if (!pAdapter) {
4800 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adapter is NULL"));
4801 return -EINVAL;
4802 }
4803
4804 status = wlan_hdd_validate_context(pHddCtx);
4805 if (0 != status) {
4806 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid HDD context"));
4807 return -EINVAL;
4808 }
4809 if (pHddCtx->cfg_ini->fTDLSExternalControl == FALSE) {
4810 hddLog(VOS_TRACE_LEVEL_ERROR, FL("TDLS external control is disabled"));
4811 return -ENOTSUPP;
4812 }
4813 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX,
4814 data, data_len,
4815 wlan_hdd_tdls_config_disable_policy)) {
4816 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
4817 return -EINVAL;
4818 }
4819 /* Parse and fetch mac address */
4820 if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]) {
4821 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac addr failed"));
4822 return -EINVAL;
4823 }
4824
4825 memcpy(peer, nla_data(
4826 tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR]),
4827 sizeof(peer));
4828 hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(peer));
4829
4830 ret = wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer);
4831
4832 EXIT();
4833 return ret;
4834}
4835
4836static int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
4837 struct wireless_dev *wdev,
4838 const void *data,
4839 int data_len)
4840{
4841 int ret = 0;
4842
4843 vos_ssr_protect(__func__);
4844 ret = __wlan_hdd_cfg80211_exttdls_disable(wiphy, wdev, data, data_len);
4845 vos_ssr_unprotect(__func__);
4846
4847 return ret;
4848}
4849
4850static int
4851__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4852 struct wireless_dev *wdev,
4853 const void *data, int data_len)
4854{
4855 struct net_device *dev = wdev->netdev;
4856 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4857 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4858 struct sk_buff *skb = NULL;
4859 tANI_U32 fset = 0;
4860 int ret = 0;
4861
4862 ENTER();
4863
4864 ret = wlan_hdd_validate_context(pHddCtx);
4865 if (0 != ret)
4866 {
4867 return ret;
4868 }
4869 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
4870 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
4871 fset |= WIFI_FEATURE_INFRA;
4872 }
4873
4874 if (TRUE == hdd_is_5g_supported(pHddCtx)) {
4875 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
4876 fset |= WIFI_FEATURE_INFRA_5G;
4877 }
4878
4879#ifdef WLAN_FEATURE_P2P
4880 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
4881 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
4882 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
4883 fset |= WIFI_FEATURE_P2P;
4884 }
4885#endif
4886
4887 /* Soft-AP is supported currently by default */
4888 fset |= WIFI_FEATURE_SOFT_AP;
4889
4890 /* HOTSPOT is a supplicant feature, enable it by default */
4891 fset |= WIFI_FEATURE_HOTSPOT;
4892
4893#ifdef WLAN_FEATURE_EXTSCAN
4894 if ((TRUE == pHddCtx->cfg_ini->fEnableEXTScan) &&
4895 sme_IsFeatureSupportedByFW(EXTENDED_SCAN)) {
4896 hddLog(LOG1, FL("EXTScan is supported by firmware"));
4897 fset |= WIFI_FEATURE_EXTSCAN;
4898 }
4899#endif
4900
4901 if (sme_IsFeatureSupportedByFW(NAN)) {
4902 hddLog(LOG1, FL("NAN is supported by firmware"));
4903 fset |= WIFI_FEATURE_NAN;
4904 }
4905
4906 /* D2D RTT is not supported currently by default */
4907 if (sme_IsFeatureSupportedByFW(RTT)) {
4908 hddLog(LOG1, FL("RTT is supported by firmware"));
4909 fset |= WIFI_FEATURE_D2AP_RTT;
4910 }
4911
4912#ifdef FEATURE_WLAN_BATCH_SCAN
4913 if (fset & WIFI_FEATURE_EXTSCAN) {
4914 hddLog(LOG1, FL("Batch scan is supported as extscan is supported"));
4915 fset &= ~WIFI_FEATURE_BATCH_SCAN;
4916 } else if (sme_IsFeatureSupportedByFW(BATCH_SCAN)) {
4917 hddLog(LOG1, FL("Batch scan is supported by firmware"));
4918 fset |= WIFI_FEATURE_BATCH_SCAN;
4919 }
4920#endif
4921
4922#ifdef FEATURE_WLAN_SCAN_PNO
4923 if (pHddCtx->cfg_ini->configPNOScanSupport &&
4924 (eHAL_STATUS_SUCCESS == wlan_hdd_is_pno_allowed(pAdapter))) {
4925 hddLog(LOG1, FL("PNO is supported by firmware"));
4926 fset |= WIFI_FEATURE_PNO;
4927 }
4928#endif
4929
4930 /* STA+STA is supported currently by default */
4931 fset |= WIFI_FEATURE_ADDITIONAL_STA;
4932
4933#ifdef FEATURE_WLAN_TDLS
4934 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSSupport) &&
4935 sme_IsFeatureSupportedByFW(TDLS)) {
4936 hddLog(LOG1, FL("TDLS is supported by firmware"));
4937 fset |= WIFI_FEATURE_TDLS;
4938 }
4939
4940 /* TDLS_OFFCHANNEL is not supported currently by default */
4941#endif
4942
4943#ifdef WLAN_AP_STA_CONCURRENCY
4944 /* AP+STA concurrency is supported currently by default */
4945 fset |= WIFI_FEATURE_AP_STA;
4946#endif
4947
4948#ifdef WLAN_FEATURE_LINK_LAYER_STATS
4949 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
4950 hddLog(LOG1, FL("Link layer stats is supported by driver"));
4951#endif
4952
4953 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
4954 NLMSG_HDRLEN);
4955
4956 if (!skb) {
4957 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
4958 return -EINVAL;
4959 }
4960 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
4961
4962 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
4963 hddLog(LOGE, FL("nla put fail"));
4964 goto nla_put_failure;
4965 }
4966
4967 ret = cfg80211_vendor_cmd_reply(skb);
4968 EXIT();
4969 return ret;
4970
4971nla_put_failure:
4972 kfree_skb(skb);
4973 return -EINVAL;
4974}
4975
4976static int
4977wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4978 struct wireless_dev *wdev,
4979 const void *data, int data_len)
4980{
4981 int ret = 0;
4982
4983 vos_ssr_protect(__func__);
4984 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev, data, data_len);
4985 vos_ssr_unprotect(__func__);
4986
4987 return ret;
4988}
4989
Gururaj Patil6b8abb32019-09-23 13:48:29 +00004990#define MAX_CONCURRENT_MATRIX \
4991 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX
4992#define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \
4993 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX
4994static const struct nla_policy
4995wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = {
4996 [MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32},
4997};
4998
chrmhoffmannbb97ca42017-05-13 21:27:44 +02004999static int
5000__wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
5001 struct wireless_dev *wdev,
5002 const void *data, int data_len)
5003{
5004 uint32_t feature_set_matrix[WLAN_HDD_MAX_FEATURE_SET] = {0};
5005 uint8_t i, feature_sets, max_feature_sets;
Gururaj Patil6b8abb32019-09-23 13:48:29 +00005006 struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1];
chrmhoffmannbb97ca42017-05-13 21:27:44 +02005007 struct sk_buff *reply_skb;
5008 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5009 int ret;
5010
5011 ENTER();
5012
5013 ret = wlan_hdd_validate_context(pHddCtx);
5014 if (0 != ret)
5015 {
5016 return ret;
5017 }
5018
Gururaj Patil6b8abb32019-09-23 13:48:29 +00005019 if (nla_parse(tb, MAX_CONCURRENT_MATRIX,
5020 data, data_len, wlan_hdd_get_concurrency_matrix_policy)) {
chrmhoffmannbb97ca42017-05-13 21:27:44 +02005021 hddLog(LOGE, FL("Invalid ATTR"));
5022 return -EINVAL;
5023 }
5024
5025 /* Parse and fetch max feature set */
Gururaj Patil6b8abb32019-09-23 13:48:29 +00005026 if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
chrmhoffmannbb97ca42017-05-13 21:27:44 +02005027 hddLog(LOGE, FL("Attr max feature set size failed"));
5028 return -EINVAL;
5029 }
Gururaj Patil6b8abb32019-09-23 13:48:29 +00005030
5031 max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
chrmhoffmannbb97ca42017-05-13 21:27:44 +02005032 hddLog(LOG1, FL("Max feature set size (%d)"), max_feature_sets);
5033
5034 /* Fill feature combination matrix */
5035 feature_sets = 0;
5036 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
5037 WIFI_FEATURE_P2P;
5038
5039 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
5040 WIFI_FEATURE_SOFT_AP;
5041
5042 feature_set_matrix[feature_sets++] = WIFI_FEATURE_P2P |
5043 WIFI_FEATURE_SOFT_AP;
5044
5045 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
5046 WIFI_FEATURE_SOFT_AP |
5047 WIFI_FEATURE_P2P;
5048
5049 /* Add more feature combinations here */
5050
5051 feature_sets = VOS_MIN(feature_sets, max_feature_sets);
5052 hddLog(LOG1, FL("Number of feature sets (%d)"), feature_sets);
5053 hddLog(LOG1, "Feature set matrix");
5054 for (i = 0; i < feature_sets; i++)
5055 hddLog(LOG1, "[%d] 0x%02X", i, feature_set_matrix[i]);
5056
5057 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5058 sizeof(u32) * feature_sets +
5059 NLMSG_HDRLEN);
5060
5061 if (reply_skb) {
5062 if (nla_put_u32(reply_skb,
5063 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
5064 feature_sets) ||
5065 nla_put(reply_skb,
5066 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
5067 sizeof(u32) * feature_sets, feature_set_matrix)) {
5068 hddLog(LOGE, FL("nla put fail"));
5069 kfree_skb(reply_skb);
5070 return -EINVAL;
5071 }
5072
5073 ret = cfg80211_vendor_cmd_reply(reply_skb);
5074 EXIT();
5075 return ret;
5076 }
5077 hddLog(LOGE, FL("Feature set matrix: buffer alloc fail"));
5078 return -ENOMEM;
5079
5080}
5081
Gururaj Patil6b8abb32019-09-23 13:48:29 +00005082#undef MAX_CONCURRENT_MATRIX
5083#undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX
5084
chrmhoffmannbb97ca42017-05-13 21:27:44 +02005085static int
5086wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
5087 struct wireless_dev *wdev,
5088 const void *data, int data_len)
5089{
5090 int ret = 0;
5091
5092 vos_ssr_protect(__func__);
5093 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev, data,
5094 data_len);
5095 vos_ssr_unprotect(__func__);
5096
5097 return ret;
5098}
5099
5100static const struct nla_policy
5101wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
5102 +1] =
5103{
5104 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
5105};
5106
5107static int __wlan_hdd_cfg80211_disable_dfs_channels(struct wiphy *wiphy,
5108 struct wireless_dev *wdev,
5109 const void *data,
5110 int data_len)
5111{
5112 struct net_device *dev = wdev->netdev;
5113 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5114 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5115 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5116 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
5117 eHalStatus status;
5118 u32 dfsFlag = 0;
5119
5120 ENTER();
5121
5122 status = wlan_hdd_validate_context(pHddCtx);
5123 if (0 != status) {
5124 return -EINVAL;
5125 }
5126 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
5127 data, data_len,
5128 wlan_hdd_set_no_dfs_flag_config_policy)) {
5129 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
5130 return -EINVAL;
5131 }
5132
5133 /* Parse and fetch required bandwidth kbps */
5134 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
5135 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr dfs flag failed"));
5136 return -EINVAL;
5137 }
5138
5139 dfsFlag = nla_get_u32(
5140 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
5141 hddLog(VOS_TRACE_LEVEL_INFO, FL(" DFS flag (%d)"),
5142 dfsFlag);
5143
5144 pHddCtx->disable_dfs_flag = dfsFlag;
5145
5146 sme_disable_dfs_channel(hHal, dfsFlag);
5147 sme_FilterScanResults(hHal, pAdapter->sessionId);
5148
5149 EXIT();
5150 return 0;
5151}
5152
5153static int wlan_hdd_cfg80211_disable_dfs_channels(struct wiphy *wiphy,
5154 struct wireless_dev *wdev,
5155 const void *data,
5156 int data_len)
5157{
5158 int ret = 0;
5159
5160 vos_ssr_protect(__func__);
5161 ret = __wlan_hdd_cfg80211_disable_dfs_channels(wiphy, wdev, data, data_len);
5162 vos_ssr_unprotect(__func__);
5163
5164 return ret;
5165
5166}
5167
5168const struct
5169nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] =
5170{
5171 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = { .type = NLA_U32 },
5172 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5173};
5174
5175static int __wlan_hdd_cfg80211_firmware_roaming(struct wiphy *wiphy,
5176 struct wireless_dev *wdev, const void *data, int data_len)
5177{
5178
5179 u8 bssid[6] = {0};
5180 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5181 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
5182 eHalStatus status = eHAL_STATUS_SUCCESS;
5183 v_U32_t isFwrRoamEnabled = FALSE;
5184 int ret;
5185
5186 ENTER();
5187
5188 ret = wlan_hdd_validate_context(pHddCtx);
5189 if (0 != ret) {
5190 return ret;
5191 }
5192
5193 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
5194 data, data_len,
5195 qca_wlan_vendor_attr);
5196 if (ret){
5197 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
5198 return -EINVAL;
5199 }
5200
5201 /* Parse and fetch Enable flag */
5202 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
5203 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr enable failed"));
5204 return -EINVAL;
5205 }
5206
5207 isFwrRoamEnabled = nla_get_u32(
5208 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
5209
5210 hddLog(VOS_TRACE_LEVEL_INFO, FL("isFwrRoamEnabled (%d)"), isFwrRoamEnabled);
5211
5212 /* Parse and fetch bssid */
5213 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
5214 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bss id failed"));
5215 return -EINVAL;
5216 }
5217
5218 memcpy(bssid, nla_data(
5219 tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
5220 sizeof(bssid));
5221 hddLog(VOS_TRACE_LEVEL_INFO, FL(MAC_ADDRESS_STR),MAC_ADDR_ARRAY(bssid));
5222
5223 //Update roaming
5224 status = sme_ConfigFwrRoaming((tHalHandle)(pHddCtx->hHal), isFwrRoamEnabled);
5225 EXIT();
5226 return status;
5227}
5228
5229static int wlan_hdd_cfg80211_firmware_roaming(struct wiphy *wiphy,
5230 struct wireless_dev *wdev, const void *data, int data_len)
5231{
5232 int ret = 0;
5233
5234 vos_ssr_protect(__func__);
5235 ret = __wlan_hdd_cfg80211_firmware_roaming(wiphy, wdev, data, data_len);
5236 vos_ssr_unprotect(__func__);
5237
5238 return ret;
5239}
5240
5241/**
5242 * __wlan_hdd_cfg80211_setband() - set band
5243 * @wiphy: Pointer to wireless phy
5244 * @wdev: Pointer to wireless device
5245 * @data: Pointer to data
5246 * @data_len: Data length
5247 *
5248 * Return: 0 on success, negative errno on failure
5249 */
5250static int
5251__wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
5252 struct wireless_dev *wdev,
5253 const void *data,
5254 int data_len)
5255{
5256 struct net_device *dev = wdev->netdev;
5257 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5258 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
5259 int ret;
5260 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
5261 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 }};
5262
5263 ENTER();
5264
5265 ret = wlan_hdd_validate_context(hdd_ctx);
5266 if (0 != ret) {
5267 hddLog(LOGE, FL("HDD context is not valid"));
5268 return ret;
5269 }
5270
5271 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5272 policy)) {
5273 hddLog(LOGE, FL("Invalid ATTR"));
5274 return -EINVAL;
5275 }
5276
5277 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
5278 hddLog(LOGE, FL("attr QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE failed"));
5279 return -EINVAL;
5280 }
5281
5282 hdd_ctx->isSetBandByNL = TRUE;
5283 ret = hdd_setBand(dev,
5284 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
5285 hdd_ctx->isSetBandByNL = FALSE;
5286
5287 EXIT();
5288 return ret;
5289}
5290
5291/**
5292 * wlan_hdd_cfg80211_setband() - Wrapper to offload packets
5293 * @wiphy: wiphy structure pointer
5294 * @wdev: Wireless device structure pointer
5295 * @data: Pointer to the data received
5296 * @data_len: Length of @data
5297 *
5298 * Return: 0 on success; errno on failure
5299 */
5300static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
5301 struct wireless_dev *wdev,
5302 const void *data,
5303 int data_len)
5304{
5305 int ret = 0;
5306
5307 vos_ssr_protect(__func__);
5308 ret = __wlan_hdd_cfg80211_setband(wiphy,
5309 wdev, data, data_len);
5310 vos_ssr_unprotect(__func__);
5311
5312 return ret;
5313}
5314
5315const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
5316{
5317 {
5318 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5319 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
5320 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5321 WIPHY_VENDOR_CMD_NEED_NETDEV |
5322 WIPHY_VENDOR_CMD_NEED_RUNNING,
5323 .doit = wlan_hdd_cfg80211_firmware_roaming
5324 },
5325
5326 {
5327 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5328 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
5329 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5330 WIPHY_VENDOR_CMD_NEED_NETDEV |
5331 WIPHY_VENDOR_CMD_NEED_RUNNING,
5332 .doit = wlan_hdd_cfg80211_nan_request
5333 },
5334
5335#ifdef WLAN_FEATURE_LINK_LAYER_STATS
5336 {
5337 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5338 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
5339 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5340 WIPHY_VENDOR_CMD_NEED_NETDEV |
5341 WIPHY_VENDOR_CMD_NEED_RUNNING,
5342 .doit = wlan_hdd_cfg80211_ll_stats_clear
5343 },
5344
5345 {
5346 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5347 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
5348 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5349 WIPHY_VENDOR_CMD_NEED_NETDEV |
5350 WIPHY_VENDOR_CMD_NEED_RUNNING,
5351 .doit = wlan_hdd_cfg80211_ll_stats_set
5352 },
5353
5354 {
5355 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5356 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
5357 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5358 WIPHY_VENDOR_CMD_NEED_NETDEV |
5359 WIPHY_VENDOR_CMD_NEED_RUNNING,
5360 .doit = wlan_hdd_cfg80211_ll_stats_get
5361 },
5362#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
5363#ifdef WLAN_FEATURE_EXTSCAN
5364 {
5365 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5366 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
5367 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5368 WIPHY_VENDOR_CMD_NEED_NETDEV |
5369 WIPHY_VENDOR_CMD_NEED_RUNNING,
5370 .doit = wlan_hdd_cfg80211_extscan_start
5371 },
5372 {
5373 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5374 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
5375 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5376 WIPHY_VENDOR_CMD_NEED_NETDEV |
5377 WIPHY_VENDOR_CMD_NEED_RUNNING,
5378 .doit = wlan_hdd_cfg80211_extscan_stop
5379 },
5380 {
5381 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5382 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
5383 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5384 WIPHY_VENDOR_CMD_NEED_NETDEV,
5385 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
5386 },
5387 {
5388 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5389 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
5390 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5391 WIPHY_VENDOR_CMD_NEED_NETDEV |
5392 WIPHY_VENDOR_CMD_NEED_RUNNING,
5393 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
5394 },
5395 {
5396 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5397 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
5398 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5399 WIPHY_VENDOR_CMD_NEED_NETDEV |
5400 WIPHY_VENDOR_CMD_NEED_RUNNING,
5401 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
5402 },
5403 {
5404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
5406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5407 WIPHY_VENDOR_CMD_NEED_NETDEV |
5408 WIPHY_VENDOR_CMD_NEED_RUNNING,
5409 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
5410 },
5411 {
5412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5413 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
5414 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5415 WIPHY_VENDOR_CMD_NEED_NETDEV |
5416 WIPHY_VENDOR_CMD_NEED_RUNNING,
5417 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
5418 },
5419 {
5420 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5421 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
5422 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5423 WIPHY_VENDOR_CMD_NEED_NETDEV |
5424 WIPHY_VENDOR_CMD_NEED_RUNNING,
5425 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
5426 },
5427 {
5428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5429 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
5430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5431 WIPHY_VENDOR_CMD_NEED_NETDEV |
5432 WIPHY_VENDOR_CMD_NEED_RUNNING,
5433 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
5434 },
5435#endif /* WLAN_FEATURE_EXTSCAN */
5436/*EXT TDLS*/
5437 {
5438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
5440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5441 WIPHY_VENDOR_CMD_NEED_NETDEV |
5442 WIPHY_VENDOR_CMD_NEED_RUNNING,
5443 .doit = wlan_hdd_cfg80211_exttdls_enable
5444 },
5445 {
5446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
5448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5449 WIPHY_VENDOR_CMD_NEED_NETDEV |
5450 WIPHY_VENDOR_CMD_NEED_RUNNING,
5451 .doit = wlan_hdd_cfg80211_exttdls_disable
5452 },
5453 {
5454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5455 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
5456 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5457 WIPHY_VENDOR_CMD_NEED_NETDEV,
5458 .doit = wlan_hdd_cfg80211_exttdls_get_status
5459 },
5460 {
5461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
5463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5464 WIPHY_VENDOR_CMD_NEED_NETDEV,
5465 .doit = wlan_hdd_cfg80211_get_supported_features
5466 },
5467 {
5468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
5470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5471 WIPHY_VENDOR_CMD_NEED_NETDEV,
5472 .doit = wlan_hdd_cfg80211_disable_dfs_channels
5473 },
5474 {
5475 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5476 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MAC_OUI,
5477 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5478 WIPHY_VENDOR_CMD_NEED_NETDEV,
5479 .doit = wlan_hdd_cfg80211_set_spoofed_mac_oui
5480 },
5481 {
5482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5483 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
5484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5485 WIPHY_VENDOR_CMD_NEED_NETDEV,
5486 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
5487 },
5488 {
5489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5490 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
5491 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5492 WIPHY_VENDOR_CMD_NEED_NETDEV |
5493 WIPHY_VENDOR_CMD_NEED_RUNNING,
5494 .doit = wlan_hdd_cfg80211_setband
5495 }
5496};
5497
5498/* vendor specific events */
5499static const
5500struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
5501{
5502#ifdef FEATURE_WLAN_CH_AVOID
5503 {
5504 .vendor_id = QCA_NL80211_VENDOR_ID,
5505 .subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
5506 },
5507#endif /* FEATURE_WLAN_CH_AVOID Index = 0*/
5508#ifdef WLAN_FEATURE_LINK_LAYER_STATS
5509 {
5510 /* Index = 1*/
5511 .vendor_id = QCA_NL80211_VENDOR_ID,
5512 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
5513 },
5514 {
5515 /* Index = 2*/
5516 .vendor_id = QCA_NL80211_VENDOR_ID,
5517 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
5518 },
5519 {
5520 /* Index = 3*/
5521 .vendor_id = QCA_NL80211_VENDOR_ID,
5522 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
5523 },
5524 {
5525 /* Index = 4*/
5526 .vendor_id = QCA_NL80211_VENDOR_ID,
5527 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
5528 },
5529 {
5530 /* Index = 5*/
5531 .vendor_id = QCA_NL80211_VENDOR_ID,
5532 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
5533 },
5534 {
5535 /* Index = 6*/
5536 .vendor_id = QCA_NL80211_VENDOR_ID,
5537 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
5538 },
5539#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
5540#ifdef WLAN_FEATURE_EXTSCAN
5541 {
5542 .vendor_id = QCA_NL80211_VENDOR_ID,
5543 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
5544 },
5545 {
5546 .vendor_id = QCA_NL80211_VENDOR_ID,
5547 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
5548 },
5549 {
5550 .vendor_id = QCA_NL80211_VENDOR_ID,
5551 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
5552 },
5553 {
5554 .vendor_id = QCA_NL80211_VENDOR_ID,
5555 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
5556 },
5557 {
5558 .vendor_id = QCA_NL80211_VENDOR_ID,
5559 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
5560 },
5561 {
5562 .vendor_id = QCA_NL80211_VENDOR_ID,
5563 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
5564 },
5565 {
5566 .vendor_id = QCA_NL80211_VENDOR_ID,
5567 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
5568 },
5569 {
5570 .vendor_id = QCA_NL80211_VENDOR_ID,
5571 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
5572 },
5573 {
5574 .vendor_id = QCA_NL80211_VENDOR_ID,
5575 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
5576 },
5577 {
5578 .vendor_id = QCA_NL80211_VENDOR_ID,
5579 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
5580 },
5581 {
5582 .vendor_id = QCA_NL80211_VENDOR_ID,
5583 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
5584 },
5585 {
5586 .vendor_id = QCA_NL80211_VENDOR_ID,
5587 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
5588 },
5589 {
5590 .vendor_id = QCA_NL80211_VENDOR_ID,
5591 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
5592 },
5593#endif /* WLAN_FEATURE_EXTSCAN */
5594/*EXT TDLS*/
5595 {
5596 .vendor_id = QCA_NL80211_VENDOR_ID,
5597 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
5598 },
5599
5600 {
5601 .vendor_id = QCA_NL80211_VENDOR_ID,
5602 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN
5603 },
5604
5605};
5606
5607/*
5608 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
5609 * This function is called by hdd_wlan_startup()
5610 * during initialization.
5611 * This function is used to allocate wiphy structure.
5612 */
5613struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
5614{
5615 struct wiphy *wiphy;
5616 ENTER();
5617 /*
5618 * Create wiphy device
5619 */
5620 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
5621
5622 if (!wiphy)
5623 {
5624 /* Print error and jump into err label and free the memory */
5625 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
5626 return NULL;
5627 }
5628
5629
5630 return wiphy;
5631}
5632
5633/*
5634 * FUNCTION: wlan_hdd_cfg80211_update_band
5635 * This function is called from the supplicant through a
5636 * private ioctl to change the band value
5637 */
5638int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
5639{
5640 int i, j;
5641 eNVChannelEnabledType channelEnabledState;
5642
5643 ENTER();
5644
5645 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
5646 {
5647
5648 if (NULL == wiphy->bands[i])
5649 {
5650 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
5651 __func__, i);
5652 continue;
5653 }
5654
5655 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
5656 {
5657 struct ieee80211_supported_band *band = wiphy->bands[i];
5658
5659 channelEnabledState = vos_nv_getChannelEnabledState(
5660 band->channels[j].hw_value);
5661
5662 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
5663 {
5664 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
5665 continue;
5666 }
5667 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
5668 {
5669 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
5670 continue;
5671 }
5672
5673 if (NV_CHANNEL_DISABLE == channelEnabledState ||
5674 NV_CHANNEL_INVALID == channelEnabledState)
5675 {
5676 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
5677 }
5678 else if (NV_CHANNEL_DFS == channelEnabledState)
5679 {
5680 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
5681 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
5682 }
5683 else
5684 {
5685 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
5686 |IEEE80211_CHAN_RADAR);
5687 }
5688 }
5689 }
5690 return 0;
5691}
5692/*
5693 * FUNCTION: wlan_hdd_cfg80211_init
5694 * This function is called by hdd_wlan_startup()
5695 * during initialization.
5696 * This function is used to initialize and register wiphy structure.
5697 */
5698int wlan_hdd_cfg80211_init(struct device *dev,
5699 struct wiphy *wiphy,
5700 hdd_config_t *pCfg
5701 )
5702{
5703 int i, j;
5704 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5705
5706 ENTER();
5707
5708 /* Now bind the underlying wlan device with wiphy */
5709 set_wiphy_dev(wiphy, dev);
5710
5711 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
5712
5713#ifndef CONFIG_ENABLE_LINUX_REG
5714 /* the flag for the other case would be initialzed in
5715 vos_init_wiphy_from_nv_bin */
5716 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
5717#endif
5718
5719 /* This will disable updating of NL channels from passive to
5720 * active if a beacon is received on passive channel. */
5721#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
5722 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
5723#else
5724 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
5725#endif
5726
5727
5728#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5729 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
5730 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
5731 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
5732 | WIPHY_FLAG_OFFCHAN_TX;
5733#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
5734 wiphy->regulatory_flags = REGULATORY_COUNTRY_IE_IGNORE;
5735#else
5736 wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE;
5737#endif
5738#endif
5739
5740#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
5741 if (pCfg->isFastTransitionEnabled
5742#ifdef FEATURE_WLAN_LFR
5743 || pCfg->isFastRoamIniFeatureEnabled
5744#endif
5745#ifdef FEATURE_WLAN_ESE
5746 || pCfg->isEseIniFeatureEnabled
5747#endif
5748 )
5749 {
5750 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
5751 }
5752#endif
5753#ifdef FEATURE_WLAN_TDLS
5754 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
5755 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
5756#endif
5757#ifdef FEATURE_WLAN_SCAN_PNO
5758 if (pCfg->configPNOScanSupport)
5759 {
5760 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5761 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
5762 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
5763 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
5764 }
5765#endif/*FEATURE_WLAN_SCAN_PNO*/
5766
5767#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5768 wiphy->features |= NL80211_FEATURE_HT_IBSS;
5769#endif
5770
5771#ifdef CONFIG_ENABLE_LINUX_REG
5772 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
5773 driver can still register regulatory callback and
5774 it will get regulatory settings in wiphy->band[], but
5775 driver need to determine what to do with both
5776 regulatory settings */
5777
5778 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
5779#else
5780 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
5781#endif
5782
5783 wiphy->max_scan_ssids = MAX_SCAN_SSID;
5784
5785 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
5786
5787 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
5788
5789 /* Supports STATION & AD-HOC modes right now */
5790 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
5791 | BIT(NL80211_IFTYPE_ADHOC)
5792 | BIT(NL80211_IFTYPE_P2P_CLIENT)
5793 | BIT(NL80211_IFTYPE_P2P_GO)
5794 | BIT(NL80211_IFTYPE_AP);
5795
5796 if (VOS_MONITOR_MODE == hdd_get_conparam())
5797 {
5798 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
5799 }
5800
5801 if( pCfg->advertiseConcurrentOperation )
5802 {
5803#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
5804 if( pCfg->enableMCC )
5805 {
5806 /* Currently, supports up to two channels */
5807 wlan_hdd_iface_combination.num_different_channels = 2;
5808
5809 if( !pCfg->allowMCCGODiffBI )
5810 wlan_hdd_iface_combination.beacon_int_infra_match = true;
5811
5812 }
5813 wiphy->iface_combinations = &wlan_hdd_iface_combination;
5814 wiphy->n_iface_combinations = 1;
5815#endif
5816 }
5817
5818 /* Before registering we need to update the ht capabilitied based
5819 * on ini values*/
5820 if( !pCfg->ShortGI20MhzEnable )
5821 {
5822 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5823 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5824 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5825 }
5826
5827 if( !pCfg->ShortGI40MhzEnable )
5828 {
5829 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
5830 }
5831
5832 if( !pCfg->nChannelBondingMode5GHz )
5833 {
5834 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5835 }
5836 /*
5837 * In case of static linked driver at the time of driver unload,
5838 * module exit doesn't happens. Module cleanup helps in cleaning
5839 * of static memory.
5840 * If driver load happens statically, at the time of driver unload,
5841 * wiphy flags don't get reset because of static memory.
5842 * It's better not to store channel in static memory.
5843 */
5844 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
5845 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
5846 (struct ieee80211_channel *)vos_mem_malloc(sizeof(hdd_channels_2_4_GHZ));
5847 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL)
5848 {
5849 hddLog(VOS_TRACE_LEVEL_ERROR,
5850 FL("Not enough memory to allocate channels"));
5851 return -ENOMEM;
5852 }
5853 vos_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
5854 &hdd_channels_2_4_GHZ[0],
5855 sizeof(hdd_channels_2_4_GHZ));
5856
5857 if (true == hdd_is_5g_supported(pHddCtx))
5858 {
5859 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
5860 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
5861 (struct ieee80211_channel *)vos_mem_malloc(sizeof(hdd_channels_5_GHZ));
5862 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL)
5863 {
5864 hddLog(VOS_TRACE_LEVEL_ERROR,
5865 FL("Not enough memory to allocate channels"));
5866 vos_mem_free(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
5867 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
5868 return -ENOMEM;
5869 }
5870 vos_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
5871 &hdd_channels_5_GHZ[0],
5872 sizeof(hdd_channels_5_GHZ));
5873 }
5874
5875 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
5876 {
5877
5878 if (NULL == wiphy->bands[i])
5879 {
5880 hddLog(VOS_TRACE_LEVEL_INFO,"%s: wiphy->bands[i] is NULL, i = %d",
5881 __func__, i);
5882 continue;
5883 }
5884
5885 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
5886 {
5887 struct ieee80211_supported_band *band = wiphy->bands[i];
5888
5889 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
5890 {
5891 // Enable social channels for P2P
5892 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
5893 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
5894 else
5895 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
5896 continue;
5897 }
5898 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
5899 {
5900 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
5901 continue;
5902 }
5903 }
5904 }
5905 /*Initialise the supported cipher suite details*/
5906 wiphy->cipher_suites = hdd_cipher_suites;
5907 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
5908
5909 /*signal strength in mBm (100*dBm) */
5910 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
5911
5912#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5913 wiphy->max_remain_on_channel_duration = 5000;
5914#endif
5915
5916 wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands);
5917 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
5918 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
5919 wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
5920
5921 EXIT();
5922 return 0;
5923}
5924
5925/* In this function we are registering wiphy. */
5926int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
5927{
5928 ENTER();
5929 /* Register our wiphy dev with cfg80211 */
5930 if (0 > wiphy_register(wiphy))
5931 {
5932 /* print error */
5933 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
5934 return -EIO;
5935 }
5936
5937 EXIT();
5938 return 0;
5939}
5940
5941/* In this function we are updating channel list when,
5942 regulatory domain is FCC and country code is US.
5943 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
5944 As per FCC smart phone is not a indoor device.
5945 GO should not opeate on indoor channels */
5946void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
5947{
5948 int j;
5949 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5950 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
5951 //Default counrtycode from NV at the time of wiphy initialization.
5952 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
5953 &defaultCountryCode[0]))
5954 {
5955 hddLog(LOGE, FL("Failed to get default country code from NV"));
5956 }
5957 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
5958 {
5959 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
5960 {
5961 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
5962 return;
5963 }
5964 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
5965 {
5966 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
5967 // Mark UNII -1 band channel as passive
5968 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
5969 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
5970 }
5971 }
5972}
5973/* This function registers for all frame which supplicant is interested in */
5974void wlan_hdd_cfg80211_register_frames(hdd_adapter_t* pAdapter)
5975{
5976 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5977 /* Register for all P2P action, public action etc frames */
5978 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
5979 ENTER();
5980 /* Register frame indication call back */
5981 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
5982 /* Right now we are registering these frame when driver is getting
5983 initialized. Once we will move to 2.6.37 kernel, in which we have
5984 frame register ops, we will move this code as a part of that */
5985 /* GAS Initial Request */
5986 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
5987 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
5988
5989 /* GAS Initial Response */
5990 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
5991 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
5992
5993 /* GAS Comeback Request */
5994 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
5995 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
5996
5997 /* GAS Comeback Response */
5998 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
5999 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
6000
6001 /* P2P Public Action */
6002 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
6003 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
6004 P2P_PUBLIC_ACTION_FRAME_SIZE );
6005
6006 /* P2P Action */
6007 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
6008 (v_U8_t*)P2P_ACTION_FRAME,
6009 P2P_ACTION_FRAME_SIZE );
6010
6011 /* WNM BSS Transition Request frame */
6012 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
6013 (v_U8_t*)WNM_BSS_ACTION_FRAME,
6014 WNM_BSS_ACTION_FRAME_SIZE );
6015
6016 /* WNM-Notification */
6017 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
6018 (v_U8_t*)WNM_NOTIFICATION_FRAME,
6019 WNM_NOTIFICATION_FRAME_SIZE );
6020}
6021
6022void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t* pAdapter)
6023{
6024 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6025 /* Register for all P2P action, public action etc frames */
6026 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
6027
6028 ENTER();
6029
6030 /* Right now we are registering these frame when driver is getting
6031 initialized. Once we will move to 2.6.37 kernel, in which we have
6032 frame register ops, we will move this code as a part of that */
6033 /* GAS Initial Request */
6034
6035 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6036 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
6037
6038 /* GAS Initial Response */
6039 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6040 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
6041
6042 /* GAS Comeback Request */
6043 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6044 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
6045
6046 /* GAS Comeback Response */
6047 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6048 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
6049
6050 /* P2P Public Action */
6051 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6052 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
6053 P2P_PUBLIC_ACTION_FRAME_SIZE );
6054
6055 /* P2P Action */
6056 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6057 (v_U8_t*)P2P_ACTION_FRAME,
6058 P2P_ACTION_FRAME_SIZE );
6059 /* WNM-Notification */
6060 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
6061 (v_U8_t*)WNM_NOTIFICATION_FRAME,
6062 WNM_NOTIFICATION_FRAME_SIZE );
6063}
6064
6065#ifdef FEATURE_WLAN_WAPI
6066void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
6067 const u8 *mac_addr, const u8 *key , int key_Len)
6068{
6069 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6070 tCsrRoamSetKey setKey;
6071 v_BOOL_t isConnected = TRUE;
6072 int status = 0;
6073 v_U32_t roamId= 0xFF;
6074 tANI_U8 *pKeyPtr = NULL;
6075 int n = 0;
6076
6077 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s(%d)",
6078 __func__, hdd_device_modetoString(pAdapter->device_mode),
6079 pAdapter->device_mode);
6080
6081 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
6082 setKey.keyId = key_index; // Store Key ID
6083 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
6084 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
6085 setKey.paeRole = 0 ; // the PAE role
6086 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
6087 {
6088 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
6089 }
6090 else
6091 {
6092 isConnected = hdd_connIsConnected(pHddStaCtx);
6093 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
6094 }
6095 setKey.keyLength = key_Len;
6096 pKeyPtr = setKey.Key;
6097 memcpy( pKeyPtr, key, key_Len);
6098
6099 hddLog(VOS_TRACE_LEVEL_INFO,"%s: WAPI KEY LENGTH:0x%04x",
6100 __func__, key_Len);
6101 for (n = 0 ; n < key_Len; n++)
6102 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
6103 __func__,n,setKey.Key[n]);
6104
6105 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6106 if ( isConnected )
6107 {
6108 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
6109 pAdapter->sessionId, &setKey, &roamId );
6110 }
6111 if ( status != 0 )
6112 {
6113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6114 "[%4d] sme_RoamSetKey returned ERROR status= %d",
6115 __LINE__, status );
6116 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
6117 }
6118 /* Need to clear any trace of key value in the memory.
6119 * Thus zero out the memory even though it is local
6120 * variable.
6121 */
6122 vos_mem_zero(&setKey, sizeof(setKey));
6123}
6124#endif /* FEATURE_WLAN_WAPI*/
6125
6126#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6127int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
6128 beacon_data_t **ppBeacon,
6129 struct beacon_parameters *params)
6130#else
6131int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
6132 beacon_data_t **ppBeacon,
6133 struct cfg80211_beacon_data *params,
6134 int dtim_period)
6135#endif
6136{
6137 int size;
6138 beacon_data_t *beacon = NULL;
6139 beacon_data_t *old = NULL;
6140 int head_len,tail_len;
6141
6142 ENTER();
6143 if (params->head && !params->head_len)
6144 {
6145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6146 FL("head_len is NULL"));
6147 return -EINVAL;
6148 }
6149
6150 old = pAdapter->sessionCtx.ap.beacon;
6151
6152 if (!params->head && !old)
6153 {
6154 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6155 FL("session(%d) old and new heads points to NULL"),
6156 pAdapter->sessionId);
6157 return -EINVAL;
6158 }
6159
6160 if (params->tail && !params->tail_len)
6161 {
6162 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6163 FL("tail_len is zero but tail is not NULL"));
6164 return -EINVAL;
6165 }
6166
6167#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
6168 /* Kernel 3.0 is not updating dtim_period for set beacon */
6169 if (!params->dtim_period)
6170 {
6171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6172 FL("dtim period is 0"));
6173 return -EINVAL;
6174 }
6175#endif
6176
6177 if(params->head)
6178 head_len = params->head_len;
6179 else
6180 head_len = old->head_len;
6181
6182 if(params->tail || !old)
6183 tail_len = params->tail_len;
6184 else
6185 tail_len = old->tail_len;
6186
6187 size = sizeof(beacon_data_t) + head_len + tail_len;
6188
6189 beacon = kzalloc(size, GFP_KERNEL);
6190
6191 if( beacon == NULL )
6192 {
6193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6194 FL("Mem allocation for beacon failed"));
6195 return -ENOMEM;
6196 }
6197
6198#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6199 if(params->dtim_period || !old )
6200 beacon->dtim_period = params->dtim_period;
6201 else
6202 beacon->dtim_period = old->dtim_period;
6203#else
6204 if(dtim_period || !old )
6205 beacon->dtim_period = dtim_period;
6206 else
6207 beacon->dtim_period = old->dtim_period;
6208#endif
6209
6210 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
6211 beacon->tail = beacon->head + head_len;
6212 beacon->head_len = head_len;
6213 beacon->tail_len = tail_len;
6214
6215 if(params->head) {
6216 memcpy (beacon->head,params->head,beacon->head_len);
6217 }
6218 else {
6219 if(old)
6220 memcpy (beacon->head,old->head,beacon->head_len);
6221 }
6222
6223 if(params->tail) {
6224 memcpy (beacon->tail,params->tail,beacon->tail_len);
6225 }
6226 else {
6227 if(old)
6228 memcpy (beacon->tail,old->tail,beacon->tail_len);
6229 }
6230
6231 *ppBeacon = beacon;
6232
6233 kfree(old);
6234
6235 return 0;
6236
6237}
6238
6239v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(
6240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
6241 const v_U8_t *pIes,
6242#else
6243 v_U8_t *pIes,
6244#endif
6245 int length, v_U8_t eid)
6246{
6247 int left = length;
6248 v_U8_t *ptr = (v_U8_t *)pIes;
6249 v_U8_t elem_id,elem_len;
6250
6251 while(left >= 2)
6252 {
6253 elem_id = ptr[0];
6254 elem_len = ptr[1];
6255 left -= 2;
6256 if(elem_len > left)
6257 {
6258 hddLog(VOS_TRACE_LEVEL_FATAL,
6259 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
6260 eid,elem_len,left);
6261 return NULL;
6262 }
6263 if (elem_id == eid)
6264 {
6265 return ptr;
6266 }
6267
6268 left -= elem_len;
6269 ptr += (elem_len + 2);
6270 }
6271 return NULL;
6272}
6273
6274/* Check if rate is 11g rate or not */
6275static int wlan_hdd_rate_is_11g(u8 rate)
6276{
6277 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
6278 u8 i;
6279 for (i = 0; i < 8; i++)
6280 {
6281 if(rate == gRateArray[i])
6282 return TRUE;
6283 }
6284 return FALSE;
6285}
6286
6287/* Check for 11g rate and set proper 11g only mode */
6288static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
6289 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
6290{
6291 u8 i, num_rates = pIe[0];
6292
6293 pIe += 1;
6294 for ( i = 0; i < num_rates; i++)
6295 {
6296 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
6297 {
6298 /* If rate set have 11g rate than change the mode to 11G */
6299 *pSapHw_mode = eSAP_DOT11_MODE_11g;
6300 if (pIe[i] & BASIC_RATE_MASK)
6301 {
6302 /* If we have 11g rate as basic rate, it means mode
6303 is 11g only mode.
6304 */
6305 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
6306 *pCheckRatesfor11g = FALSE;
6307 }
6308 }
6309 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
6310 {
6311 *require_ht = TRUE;
6312 }
6313 }
6314 return;
6315}
6316
6317static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
6318{
6319 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
6320 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
6321 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
6322 u8 checkRatesfor11g = TRUE;
6323 u8 require_ht = FALSE;
6324 u8 *pIe=NULL;
6325
6326 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
6327
6328 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
6329 pBeacon->head_len, WLAN_EID_SUPP_RATES);
6330 if (pIe != NULL)
6331 {
6332 pIe += 1;
6333 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
6334 &pConfig->SapHw_mode);
6335 }
6336
6337 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
6338 WLAN_EID_EXT_SUPP_RATES);
6339 if (pIe != NULL)
6340 {
6341
6342 pIe += 1;
6343 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
6344 &pConfig->SapHw_mode);
6345 }
6346
6347 if( pConfig->channel > 14 )
6348 {
6349 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
6350 }
6351
6352 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
6353 WLAN_EID_HT_CAPABILITY);
6354
6355 if(pIe)
6356 {
6357 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
6358 if(require_ht)
6359 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
6360 }
6361}
6362
6363static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
6364 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
6365{
6366 v_U16_t ielen = 0;
6367 v_U8_t *pIe = NULL;
6368 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
6369
6370 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
6371 pBeacon->tail, pBeacon->tail_len);
6372
6373 if (pIe)
6374 {
6375 ielen = pIe[1] + 2;
6376 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
6377 {
6378 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
6379 }
6380 else
6381 {
6382 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
6383 return -EINVAL;
6384 }
6385 *total_ielen += ielen;
6386 }
6387 return 0;
6388}
6389
6390static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
6391 v_U8_t *genie, v_U8_t *total_ielen)
6392{
6393 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
6394 int left = pBeacon->tail_len;
6395 v_U8_t *ptr = pBeacon->tail;
6396 v_U8_t elem_id, elem_len;
6397 v_U16_t ielen = 0;
6398
6399 if ( NULL == ptr || 0 == left )
6400 return;
6401
6402 while (left >= 2)
6403 {
6404 elem_id = ptr[0];
6405 elem_len = ptr[1];
6406 left -= 2;
6407 if (elem_len > left)
6408 {
6409 hddLog( VOS_TRACE_LEVEL_ERROR,
6410 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
6411 elem_id, elem_len, left);
6412 return;
6413 }
6414 if (IE_EID_VENDOR == elem_id)
6415 {
6416 /* skipping the VSIE's which we don't want to include or
6417 * it will be included by existing code
6418 */
6419 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
6420#ifdef WLAN_FEATURE_WFD
6421 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
6422#endif
6423 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
6424 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
6425 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
6426 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
6427 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
6428 {
6429 ielen = ptr[1] + 2;
6430 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
6431 {
6432 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
6433 *total_ielen += ielen;
6434 }
6435 else
6436 {
6437 hddLog( VOS_TRACE_LEVEL_ERROR,
6438 "IE Length is too big "
6439 "IEs eid=%d elem_len=%d total_ie_lent=%d",
6440 elem_id, elem_len, *total_ielen);
6441 }
6442 }
6443 }
6444
6445 left -= elem_len;
6446 ptr += (elem_len + 2);
6447 }
6448 return;
6449}
6450
6451#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6452static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
6453 struct beacon_parameters *params)
6454#else
6455static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
6456 struct cfg80211_beacon_data *params)
6457#endif
6458{
6459 v_U8_t *genie;
6460 v_U8_t total_ielen = 0;
6461 v_U8_t addIE[1] = {0};
6462 int ret = 0;
6463
6464 genie = vos_mem_malloc(MAX_GENIE_LEN);
6465
6466 if(genie == NULL) {
6467
6468 return -ENOMEM;
6469 }
6470
6471 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
6472 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
6473 {
6474 hddLog(LOGE,
6475 FL("Adding WPS IE failed"));
6476 ret = -EINVAL;
6477 goto done;
6478 }
6479
6480#ifdef WLAN_FEATURE_WFD
6481 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
6482 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
6483 {
6484 hddLog(LOGE,
6485 FL("Adding WFD IE failed"));
6486 ret = -EINVAL;
6487 goto done;
6488 }
6489#endif
6490
6491 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
6492 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
6493 {
6494 hddLog(LOGE,
6495 FL("Adding P2P IE failed"));
6496 ret = -EINVAL;
6497 goto done;
6498 }
6499
6500 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
6501 {
6502 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
6503 }
6504
6505 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6506 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
6507 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
6508 {
6509 hddLog(LOGE,
6510 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
6511 ret = -EINVAL;
6512 goto done;
6513 }
6514
6515 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6516 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
6517 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
6518 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
6519 ==eHAL_STATUS_FAILURE)
6520 {
6521 hddLog(LOGE,
6522 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
6523 ret = -EINVAL;
6524 goto done;
6525 }
6526
6527 // Added for ProResp IE
6528 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
6529 {
6530 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
6531 u8 probe_rsp_ie_len[3] = {0};
6532 u8 counter = 0;
6533 /* Check Probe Resp Length if it is greater then 255 then Store
6534 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
6535 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
6536 Store More then 255 bytes into One Variable.
6537 */
6538 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
6539 {
6540 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
6541 {
6542 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
6543 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
6544 }
6545 else
6546 {
6547 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
6548 rem_probe_resp_ie_len = 0;
6549 }
6550 }
6551
6552 rem_probe_resp_ie_len = 0;
6553
6554 if (probe_rsp_ie_len[0] > 0)
6555 {
6556 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6557 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
6558 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
6559 probe_rsp_ie_len[0], NULL,
6560 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
6561 {
6562 hddLog(LOGE,
6563 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
6564 ret = -EINVAL;
6565 goto done;
6566 }
6567 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
6568 }
6569
6570 if (probe_rsp_ie_len[1] > 0)
6571 {
6572 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6573 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
6574 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
6575 probe_rsp_ie_len[1], NULL,
6576 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
6577 {
6578 hddLog(LOGE,
6579 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
6580 ret = -EINVAL;
6581 goto done;
6582 }
6583 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
6584 }
6585
6586 if (probe_rsp_ie_len[2] > 0)
6587 {
6588 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6589 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
6590 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
6591 probe_rsp_ie_len[2], NULL,
6592 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
6593 {
6594 hddLog(LOGE,
6595 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
6596 ret = -EINVAL;
6597 goto done;
6598 }
6599 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
6600 }
6601
6602 if (probe_rsp_ie_len[1] == 0 )
6603 {
6604 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6605 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6606 eANI_BOOLEAN_FALSE) )
6607 {
6608 hddLog(LOGE,
6609 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
6610 }
6611 }
6612
6613 if (probe_rsp_ie_len[2] == 0 )
6614 {
6615 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6616 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6617 eANI_BOOLEAN_FALSE) )
6618 {
6619 hddLog(LOGE,
6620 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
6621 }
6622 }
6623
6624 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6625 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
6626 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
6627 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
6628 == eHAL_STATUS_FAILURE)
6629 {
6630 hddLog(LOGE,
6631 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
6632 ret = -EINVAL;
6633 goto done;
6634 }
6635 }
6636 else
6637 {
6638 // Reset WNI_CFG_PROBE_RSP Flags
6639 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
6640
6641 hddLog(VOS_TRACE_LEVEL_INFO,
6642 "%s: No Probe Response IE received in set beacon",
6643 __func__);
6644 }
6645
6646 // Added for AssocResp IE
6647 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
6648 {
6649 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6650 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
6651 params->assocresp_ies_len, NULL,
6652 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
6653 {
6654 hddLog(LOGE,
6655 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
6656 ret = -EINVAL;
6657 goto done;
6658 }
6659
6660 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6661 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
6662 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
6663 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
6664 == eHAL_STATUS_FAILURE)
6665 {
6666 hddLog(LOGE,
6667 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6668 ret = -EINVAL;
6669 goto done;
6670 }
6671 }
6672 else
6673 {
6674 hddLog(VOS_TRACE_LEVEL_INFO,
6675 "%s: No Assoc Response IE received in set beacon",
6676 __func__);
6677
6678 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6679 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6680 eANI_BOOLEAN_FALSE) )
6681 {
6682 hddLog(LOGE,
6683 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6684 }
6685 }
6686
6687done:
6688 vos_mem_free(genie);
6689 return ret;
6690}
6691
6692/*
6693 * FUNCTION: wlan_hdd_validate_operation_channel
6694 * called by wlan_hdd_cfg80211_start_bss() and
6695 * wlan_hdd_cfg80211_set_channel()
6696 * This function validates whether given channel is part of valid
6697 * channel list.
6698 */
6699VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
6700{
6701
6702 v_U32_t num_ch = 0;
6703 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6704 u32 indx = 0;
6705 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6706 v_U8_t fValidChannel = FALSE, count = 0;
6707 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
6708
6709 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6710
6711 if ( hdd_pConfig_ini->sapAllowAllChannel)
6712 {
6713 /* Validate the channel */
6714 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
6715 {
6716 if ( channel == rfChannels[count].channelNum )
6717 {
6718 fValidChannel = TRUE;
6719 break;
6720 }
6721 }
6722 if (fValidChannel != TRUE)
6723 {
6724 hddLog(VOS_TRACE_LEVEL_ERROR,
6725 "%s: Invalid Channel [%d]", __func__, channel);
6726 return VOS_STATUS_E_FAILURE;
6727 }
6728 }
6729 else
6730 {
6731 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6732 valid_ch, &num_ch))
6733 {
6734 hddLog(VOS_TRACE_LEVEL_ERROR,
6735 "%s: failed to get valid channel list", __func__);
6736 return VOS_STATUS_E_FAILURE;
6737 }
6738 for (indx = 0; indx < num_ch; indx++)
6739 {
6740 if (channel == valid_ch[indx])
6741 {
6742 break;
6743 }
6744 }
6745
6746 if (indx >= num_ch)
6747 {
6748 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6749 {
6750 eCsrBand band;
6751 unsigned int freq;
6752
6753 sme_GetFreqBand(hHal, &band);
6754
6755 if (eCSR_BAND_5G == band)
6756 {
6757#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
6758 if (channel <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
6759 {
6760 freq = ieee80211_channel_to_frequency(channel,
6761 IEEE80211_BAND_2GHZ);
6762 }
6763 else
6764 {
6765 freq = ieee80211_channel_to_frequency(channel,
6766 IEEE80211_BAND_5GHZ);
6767 }
6768#else
6769 freq = ieee80211_channel_to_frequency(channel);
6770#endif
6771 if(WLAN_HDD_IS_SOCIAL_CHANNEL(freq))
6772 return VOS_STATUS_SUCCESS;
6773 }
6774 }
6775
6776 hddLog(VOS_TRACE_LEVEL_ERROR,
6777 "%s: Invalid Channel [%d]", __func__, channel);
6778 return VOS_STATUS_E_FAILURE;
6779 }
6780 }
6781
6782 return VOS_STATUS_SUCCESS;
6783
6784}
6785
6786/**
6787 * FUNCTION: __wlan_hdd_cfg80211_set_channel
6788 * This function is used to set the channel number
6789 */
6790static int __wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
6791 struct ieee80211_channel *chan,
6792 enum nl80211_channel_type channel_type
6793 )
6794{
6795 hdd_adapter_t *pAdapter = NULL;
6796 v_U32_t num_ch = 0;
6797 int channel = 0;
6798 int freq = chan->center_freq; /* freq is in MHZ */
6799 hdd_context_t *pHddCtx;
6800 int status;
6801
6802 ENTER();
6803
6804 if( NULL == dev )
6805 {
6806 hddLog(VOS_TRACE_LEVEL_ERROR,
6807 "%s: Called with dev = NULL.", __func__);
6808 return -ENODEV;
6809 }
6810 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
6811
6812 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6813 TRACE_CODE_HDD_CFG80211_SET_CHANNEL, pAdapter->sessionId,
6814 channel_type ));
6815 hddLog(VOS_TRACE_LEVEL_INFO,
6816 "%s: device_mode = %s (%d) freq = %d", __func__,
6817 hdd_device_modetoString(pAdapter->device_mode),
6818 pAdapter->device_mode, chan->center_freq);
6819
6820 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6821 status = wlan_hdd_validate_context(pHddCtx);
6822 if (0 != status)
6823 {
6824 return status;
6825 }
6826
6827 /*
6828 * Do freq to chan conversion
6829 * TODO: for 11a
6830 */
6831
6832 channel = ieee80211_frequency_to_channel(freq);
6833
6834 /* Check freq range */
6835 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
6836 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
6837 {
6838 hddLog(VOS_TRACE_LEVEL_ERROR,
6839 "%s: Channel [%d] is outside valid range from %d to %d",
6840 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
6841 WNI_CFG_CURRENT_CHANNEL_STAMAX);
6842 return -EINVAL;
6843 }
6844
6845 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6846
6847 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
6848 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
6849 {
6850 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
6851 {
6852 hddLog(VOS_TRACE_LEVEL_ERROR,
6853 "%s: Invalid Channel [%d]", __func__, channel);
6854 return -EINVAL;
6855 }
6856 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6857 "%s: set channel to [%d] for device mode =%d",
6858 __func__, channel,pAdapter->device_mode);
6859 }
6860 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6861 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
6862 )
6863 {
6864 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6865 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
6866 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6867
6868 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
6869 {
6870 /* Link is up then return cant set channel*/
6871 hddLog( VOS_TRACE_LEVEL_ERROR,
6872 "%s: IBSS Associated, can't set the channel", __func__);
6873 return -EINVAL;
6874 }
6875
6876 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
6877 pHddStaCtx->conn_info.operationChannel = channel;
6878 pRoamProfile->ChannelInfo.ChannelList =
6879 &pHddStaCtx->conn_info.operationChannel;
6880 }
6881 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
6882 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
6883 )
6884 {
6885 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
6886 {
6887 if(VOS_STATUS_SUCCESS !=
6888 wlan_hdd_validate_operation_channel(pAdapter,channel))
6889 {
6890 hddLog(VOS_TRACE_LEVEL_ERROR,
6891 "%s: Invalid Channel [%d]", __func__, channel);
6892 return -EINVAL;
6893 }
6894 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
6895 }
6896 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
6897 {
6898 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
6899
6900 /* If auto channel selection is configured as enable/ 1 then ignore
6901 channel set by supplicant
6902 */
6903 if ( cfg_param->apAutoChannelSelection )
6904 {
6905 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
6906 AUTO_CHANNEL_SELECT;
6907 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6908 "%s: set channel to auto channel (0) for device mode =%s (%d)",
6909 __func__, hdd_device_modetoString(pAdapter->device_mode),
6910 pAdapter->device_mode);
6911 }
6912 else
6913 {
6914 if(VOS_STATUS_SUCCESS !=
6915 wlan_hdd_validate_operation_channel(pAdapter,channel))
6916 {
6917 hddLog(VOS_TRACE_LEVEL_ERROR,
6918 "%s: Invalid Channel [%d]", __func__, channel);
6919 return -EINVAL;
6920 }
6921 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
6922 }
6923 }
6924 }
6925 else
6926 {
6927 hddLog(VOS_TRACE_LEVEL_FATAL,
6928 "%s: Invalid device mode failed to set valid channel", __func__);
6929 return -EINVAL;
6930 }
6931 EXIT();
6932 return status;
6933}
6934
6935static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy,
6936 struct net_device *dev,
6937 struct ieee80211_channel *chan,
6938 enum nl80211_channel_type channel_type
6939 )
6940{
6941 int ret;
6942
6943 vos_ssr_protect(__func__);
6944 ret = __wlan_hdd_cfg80211_set_channel(wiphy, dev, chan, channel_type);
6945 vos_ssr_unprotect(__func__);
6946
6947 return ret;
6948}
6949
6950#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
6951static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
6952 struct beacon_parameters *params)
6953#else
6954static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
6955 struct cfg80211_beacon_data *params,
6956 const u8 *ssid, size_t ssid_len,
6957 enum nl80211_hidden_ssid hidden_ssid,
6958 v_U8_t auth_type)
6959#endif
6960{
6961 tsap_Config_t *pConfig;
6962 beacon_data_t *pBeacon = NULL;
6963 struct ieee80211_mgmt *pMgmt_frame;
6964 v_U8_t *pIe=NULL;
6965 v_U16_t capab_info;
6966 eCsrAuthType RSNAuthType;
6967 eCsrEncryptionType RSNEncryptType;
6968 eCsrEncryptionType mcRSNEncryptType;
6969 int status = VOS_STATUS_SUCCESS;
6970 tpWLAN_SAPEventCB pSapEventCallback;
6971 hdd_hostapd_state_t *pHostapdState;
6972 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
6973 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
6974 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
6975 struct qc_mac_acl_entry *acl_entry = NULL;
6976 hdd_config_t *iniConfig;
6977 v_SINT_t i;
6978 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
6979 tSmeConfigParams *psmeConfig;
6980 v_BOOL_t MFPCapable = VOS_FALSE;
6981 v_BOOL_t MFPRequired = VOS_FALSE;
6982 v_BOOL_t sapEnable11AC =
6983 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->sapEnable11AC;
6984 ENTER();
6985
6986 iniConfig = pHddCtx->cfg_ini;
6987
6988 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
6989
6990 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
6991
6992 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
6993
6994 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
6995
6996 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
6997
6998 //channel is already set in the set_channel Call back
6999 //pConfig->channel = pCommitConfig->channel;
7000
7001 /*Protection parameter to enable or disable*/
7002 pConfig->protEnabled =
7003 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
7004
7005 pConfig->dtim_period = pBeacon->dtim_period;
7006
7007 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***",
7008 pConfig->dtim_period);
7009
7010 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
7011 {
7012 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
7013 WLAN_EID_COUNTRY);
7014 if(memcmp(pHddCtx->cfg_ini->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)
7015 {
7016 tANI_BOOLEAN restartNeeded;
7017 pConfig->ieee80211d = 1;
7018 vos_mem_copy(pConfig->countryCode, pHddCtx->cfg_ini->apCntryCode, 3);
7019 sme_setRegInfo(hHal, pConfig->countryCode);
7020 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
7021 }
7022 else if(pIe)
7023 {
7024 tANI_BOOLEAN restartNeeded;
7025 pConfig->ieee80211d = 1;
7026 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
7027 sme_setRegInfo(hHal, pConfig->countryCode);
7028 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
7029 }
7030 else
7031 {
7032 pConfig->ieee80211d = 0;
7033 }
7034 /*
7035 * If auto channel is configured i.e. channel is 0,
7036 * so skip channel validation.
7037 */
7038 if( AUTO_CHANNEL_SELECT != pConfig->channel )
7039 {
7040 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
7041 {
7042 hddLog(VOS_TRACE_LEVEL_ERROR,
7043 "%s: Invalid Channel [%d]", __func__, pConfig->channel);
7044 return -EINVAL;
7045 }
7046 }
7047 else
7048 {
7049 if(1 != pHddCtx->is_dynamic_channel_range_set)
7050 {
7051 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
7052 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
7053 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
7054 }
7055 pHddCtx->is_dynamic_channel_range_set = 0;
7056 }
7057 }
7058 else
7059 {
7060 pConfig->ieee80211d = 0;
7061 }
7062
7063#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7064 if (params->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
7065 pConfig->authType = eSAP_OPEN_SYSTEM;
7066 else if (params->auth_type == NL80211_AUTHTYPE_SHARED_KEY)
7067 pConfig->authType = eSAP_SHARED_KEY;
7068 else
7069 pConfig->authType = eSAP_AUTO_SWITCH;
7070#else
7071 if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
7072 pConfig->authType = eSAP_OPEN_SYSTEM;
7073 else if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
7074 pConfig->authType = eSAP_SHARED_KEY;
7075 else
7076 pConfig->authType = eSAP_AUTO_SWITCH;
7077#endif
7078
7079 capab_info = pMgmt_frame->u.beacon.capab_info;
7080
7081 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
7082 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
7083
7084 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
7085
7086 /*Set wps station to configured*/
7087 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
7088
7089 if(pIe)
7090 {
7091 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
7092 {
7093 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***");
7094 return -EINVAL;
7095 }
7096 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
7097 {
7098 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
7099 /* Check 15 bit of WPS IE as it contain information for wps state
7100 * WPS state
7101 */
7102 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
7103 {
7104 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
7105 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
7106 {
7107 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
7108 }
7109 }
7110 }
7111 else
7112 {
7113 pConfig->wps_state = SAP_WPS_DISABLED;
7114 }
7115 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
7116
7117 pConfig->RSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
7118 pConfig->mcRSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
7119 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType =
7120 eCSR_ENCRYPT_TYPE_NONE;
7121
7122 pConfig->RSNWPAReqIELength = 0;
7123 pConfig->pRSNWPAReqIE = NULL;
7124 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
7125 WLAN_EID_RSN);
7126 if(pIe && pIe[1])
7127 {
7128 pConfig->RSNWPAReqIELength = pIe[1] + 2;
7129 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
7130 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
7131 /* The actual processing may eventually be more extensive than
7132 * this. Right now, just consume any PMKIDs that are sent in
7133 * by the app.
7134 * */
7135 status = hdd_softap_unpackIE(
7136 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
7137 &RSNEncryptType,
7138 &mcRSNEncryptType,
7139 &RSNAuthType,
7140 &MFPCapable,
7141 &MFPRequired,
7142 pConfig->pRSNWPAReqIE[1]+2,
7143 pConfig->pRSNWPAReqIE );
7144
7145 if( VOS_STATUS_SUCCESS == status )
7146 {
7147 /* Now copy over all the security attributes you have
7148 * parsed out
7149 * */
7150 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
7151 pConfig->mcRSNEncryptType = mcRSNEncryptType;
7152 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
7153 = RSNEncryptType;
7154 hddLog( LOG1, FL("CSR AuthType = %d, "
7155 "EncryptionType = %d mcEncryptionType = %d"),
7156 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
7157 }
7158 }
7159
7160 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
7161 pBeacon->tail, pBeacon->tail_len);
7162
7163 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
7164 {
7165 if (pConfig->pRSNWPAReqIE)
7166 {
7167 /*Mixed mode WPA/WPA2*/
7168 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
7169 pConfig->RSNWPAReqIELength += pIe[1] + 2;
7170 }
7171 else
7172 {
7173 pConfig->RSNWPAReqIELength = pIe[1] + 2;
7174 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
7175 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
7176 status = hdd_softap_unpackIE(
7177 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
7178 &RSNEncryptType,
7179 &mcRSNEncryptType,
7180 &RSNAuthType,
7181 &MFPCapable,
7182 &MFPRequired,
7183 pConfig->pRSNWPAReqIE[1]+2,
7184 pConfig->pRSNWPAReqIE );
7185
7186 if( VOS_STATUS_SUCCESS == status )
7187 {
7188 /* Now copy over all the security attributes you have
7189 * parsed out
7190 * */
7191 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
7192 pConfig->mcRSNEncryptType = mcRSNEncryptType;
7193 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
7194 = RSNEncryptType;
7195 hddLog( LOG1, FL("CSR AuthType = %d, "
7196 "EncryptionType = %d mcEncryptionType = %d"),
7197 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
7198 }
7199 }
7200 }
7201
7202 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
7203 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
7204 return -EINVAL;
7205 }
7206
7207 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
7208
7209#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7210 if (params->ssid != NULL)
7211 {
7212 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
7213 pConfig->SSIDinfo.ssid.length = params->ssid_len;
7214 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
7215 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
7216 }
7217#else
7218 if (ssid != NULL)
7219 {
7220 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
7221 pConfig->SSIDinfo.ssid.length = ssid_len;
7222 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
7223 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
7224 }
7225#endif
7226
7227 vos_mem_copy(pConfig->self_macaddr.bytes,
7228 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
7229
7230 /* default value */
7231 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
7232 pConfig->num_accept_mac = 0;
7233 pConfig->num_deny_mac = 0;
7234
7235 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
7236 pBeacon->tail, pBeacon->tail_len);
7237
7238 /* pIe for black list is following form:
7239 type : 1 byte
7240 length : 1 byte
7241 OUI : 4 bytes
7242 acl type : 1 byte
7243 no of mac addr in black list: 1 byte
7244 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
7245 */
7246 if ((pIe != NULL) && (pIe[1] != 0))
7247 {
7248 pConfig->SapMacaddr_acl = pIe[6];
7249 pConfig->num_deny_mac = pIe[7];
7250 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d",
7251 pIe[6], pIe[7]);
7252 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
7253 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
7254 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
7255 for (i = 0; i < pConfig->num_deny_mac; i++)
7256 {
7257 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
7258 acl_entry++;
7259 }
7260 }
7261 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
7262 pBeacon->tail, pBeacon->tail_len);
7263
7264 /* pIe for white list is following form:
7265 type : 1 byte
7266 length : 1 byte
7267 OUI : 4 bytes
7268 acl type : 1 byte
7269 no of mac addr in white list: 1 byte
7270 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
7271 */
7272 if ((pIe != NULL) && (pIe[1] != 0))
7273 {
7274 pConfig->SapMacaddr_acl = pIe[6];
7275 pConfig->num_accept_mac = pIe[7];
7276 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d",
7277 pIe[6], pIe[7]);
7278 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
7279 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
7280 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
7281 for (i = 0; i < pConfig->num_accept_mac; i++)
7282 {
7283 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
7284 acl_entry++;
7285 }
7286 }
7287
7288 wlan_hdd_set_sapHwmode(pHostapdAdapter);
7289
7290#ifdef WLAN_FEATURE_11AC
7291 /* Overwrite the hostapd setting for HW mode only for 11ac.
7292 * This is valid only if mode is set to 11n in hostapd, sapEnable11AC
7293 * is set in .ini and 11ac is supported by both host and firmware.
7294 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode)
7295 */
7296 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
7297 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
7298 (sapEnable11AC) && (sme_IsFeatureSupportedByDriver(DOT11AC)) &&
7299 (sme_IsFeatureSupportedByFW(DOT11AC)) )
7300 {
7301 v_U32_t operatingBand = 0;
7302 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
7303 ccmCfgGetInt(hHal, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, &operatingBand);
7304
7305 /* If ACS disable and selected channel <= 14
7306 * OR
7307 * ACS enabled and ACS operating band is choosen as 2.4
7308 * AND
7309 * VHT in 2.4G Disabled
7310 * THEN
7311 * Fallback to 11N mode
7312 */
7313 if (((AUTO_CHANNEL_SELECT != pConfig->channel && pConfig->channel <= SIR_11B_CHANNEL_END)
7314 || (AUTO_CHANNEL_SELECT == pConfig->channel &&
7315 operatingBand == eSAP_RF_SUBBAND_2_4_GHZ)) &&
7316 iniConfig->enableVhtFor24GHzBand == FALSE)
7317 {
7318 hddLog(LOGW, FL("Setting hwmode to 11n, operatingBand = %d, Channel = %d"),
7319 operatingBand, pConfig->channel);
7320 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
7321 }
7322 }
7323#endif
7324
7325 // ht_capab is not what the name conveys,this is used for protection bitmap
7326 pConfig->ht_capab =
7327 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
7328
7329 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
7330 {
7331 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
7332 return -EINVAL;
7333 }
7334
7335 //Uapsd Enabled Bit
7336 pConfig->UapsdEnable =
7337 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
7338 //Enable OBSS protection
7339 pConfig->obssProtEnabled =
7340 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
7341
7342#ifdef WLAN_FEATURE_11W
7343 pConfig->mfpCapable = MFPCapable;
7344 pConfig->mfpRequired = MFPRequired;
7345 hddLog(LOGW, FL("Soft AP MFP capable %d, MFP required %d\n"),
7346 pConfig->mfpCapable, pConfig->mfpRequired);
7347#endif
7348
7349 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR),
7350 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
7351 hddLog(LOGW,FL("ssid =%s, beaconint=%d, channel=%d"),
7352 pConfig->SSIDinfo.ssid.ssId, (int)pConfig->beacon_int,
7353 (int)pConfig->channel);
7354 hddLog(LOGW,FL("hw_mode=%x, privacy=%d, authType=%d"),
7355 pConfig->SapHw_mode, pConfig->privacy,
7356 pConfig->authType);
7357 hddLog(LOGW,FL("RSN/WPALen=%d, Uapsd = %d"),
7358 (int)pConfig->RSNWPAReqIELength, pConfig->UapsdEnable);
7359 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d"),
7360 pConfig->protEnabled, pConfig->obssProtEnabled);
7361
7362 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
7363 {
7364 //Bss already started. just return.
7365 //TODO Probably it should update some beacon params.
7366 hddLog( LOGE, "Bss Already started...Ignore the request");
7367 EXIT();
7368 return 0;
7369 }
7370
7371 if (vos_max_concurrent_connections_reached()) {
7372 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
7373 return -EINVAL;
7374 }
7375
7376 pConfig->persona = pHostapdAdapter->device_mode;
7377
7378 psmeConfig = (tSmeConfigParams*) vos_mem_malloc(sizeof(tSmeConfigParams));
7379 if ( NULL != psmeConfig)
7380 {
7381 vos_mem_zero(psmeConfig, sizeof (tSmeConfigParams));
7382 sme_GetConfigParam(hHal, psmeConfig);
7383 pConfig->scanBandPreference = psmeConfig->csrConfig.scanBandPreference;
7384#ifdef WLAN_FEATURE_AP_HT40_24G
7385 if (((pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
7386 || (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO))
7387 && pHddCtx->cfg_ini->apHT40_24GEnabled)
7388 {
7389 psmeConfig->csrConfig.apHT40_24GEnabled = 1;
7390 sme_UpdateConfig (hHal, psmeConfig);
7391 }
7392#endif
7393 vos_mem_free(psmeConfig);
7394 }
7395 pConfig->acsBandSwitchThreshold = iniConfig->acsBandSwitchThreshold;
7396
7397 pSapEventCallback = hdd_hostapd_SAPEventCB;
7398 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
7399 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
7400 {
7401 hddLog(LOGE,FL("SAP Start Bss fail"));
7402 return -EINVAL;
7403 }
7404
7405 hddLog(LOG1,
7406 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
7407
7408 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
7409
7410 if (!VOS_IS_STATUS_SUCCESS(status))
7411 {
7412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7413 ("ERROR: HDD vos wait for single_event failed!!"));
7414 smeGetCommandQStatus(hHal);
7415 VOS_ASSERT(0);
7416 }
7417
7418 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
7419 /* Initialize WMM configuation */
7420 hdd_wmm_init(pHostapdAdapter);
7421 wlan_hdd_incr_active_session(pHddCtx, pHostapdAdapter->device_mode);
7422
7423#ifdef WLAN_FEATURE_P2P_DEBUG
7424 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
7425 {
7426 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
7427 {
7428 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
7429 hddLog(LOGE,"[P2P State] From Go nego completed to "
7430 "Non-autonomous Group started");
7431 }
7432 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
7433 {
7434 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
7435 hddLog(LOGE,"[P2P State] From Inactive to "
7436 "Autonomous Group started");
7437 }
7438 }
7439#endif
7440
7441 pHostapdState->bCommit = TRUE;
7442 EXIT();
7443
7444 return 0;
7445}
7446
7447#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7448static int __wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
7449 struct net_device *dev,
7450 struct beacon_parameters *params)
7451{
7452 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7453 hdd_context_t *pHddCtx;
7454 int status;
7455
7456 ENTER();
7457
7458 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7459 TRACE_CODE_HDD_CFG80211_ADD_BEACON,
7460 pAdapter->sessionId, params->interval));
7461 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%s (%d)",
7462 hdd_device_modetoString(pAdapter->device_mode),
7463 pAdapter->device_mode);
7464
7465 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7466 status = wlan_hdd_validate_context(pHddCtx);
7467 if (0 != status)
7468 {
7469 return status;
7470 }
7471
7472 if (vos_max_concurrent_connections_reached()) {
7473 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
7474 return -EINVAL;
7475 }
7476
7477 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
7478 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
7479 )
7480 {
7481 beacon_data_t *old,*new;
7482
7483 old = pAdapter->sessionCtx.ap.beacon;
7484
7485 if (old)
7486 {
7487 hddLog(VOS_TRACE_LEVEL_WARN,
7488 FL("already beacon info added to session(%d)"),
7489 pAdapter->sessionId);
7490 return -EALREADY;
7491 }
7492
7493 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
7494
7495 if(status != VOS_STATUS_SUCCESS)
7496 {
7497 hddLog(VOS_TRACE_LEVEL_FATAL,
7498 "%s:Error!!! Allocating the new beacon",__func__);
7499 return -EINVAL;
7500 }
7501
7502 pAdapter->sessionCtx.ap.beacon = new;
7503
7504 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
7505 }
7506
7507 EXIT();
7508 return status;
7509}
7510
7511static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
7512 struct net_device *dev,
7513 struct beacon_parameters *params)
7514{
7515 int ret;
7516
7517 vos_ssr_protect(__func__);
7518 ret = __wlan_hdd_cfg80211_add_beacon(wiphy, dev, params);
7519 vos_ssr_unprotect(__func__);
7520
7521 return ret;
7522}
7523
7524static int __wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
7525 struct net_device *dev,
7526 struct beacon_parameters *params)
7527{
7528 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7529 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7530 hdd_context_t *pHddCtx;
7531 int status;
7532
7533 ENTER();
7534
7535 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7536 TRACE_CODE_HDD_CFG80211_SET_BEACON,
7537 pAdapter->sessionId, pHddStaCtx->conn_info.authType));
7538 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
7539 __func__, hdd_device_modetoString(pAdapter->device_mode),
7540 pAdapter->device_mode);
7541
7542 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7543 status = wlan_hdd_validate_context(pHddCtx);
7544 if (0 != status)
7545 {
7546 return status;
7547 }
7548
7549 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
7550 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
7551 )
7552 {
7553 beacon_data_t *old,*new;
7554
7555 old = pAdapter->sessionCtx.ap.beacon;
7556
7557 if (!old)
7558 {
7559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7560 FL("session(%d) old and new heads points to NULL"),
7561 pAdapter->sessionId);
7562 return -ENOENT;
7563 }
7564
7565 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
7566
7567 if(status != VOS_STATUS_SUCCESS) {
7568 hddLog(VOS_TRACE_LEVEL_FATAL,
7569 "%s: Error!!! Allocating the new beacon",__func__);
7570 return -EINVAL;
7571 }
7572
7573 pAdapter->sessionCtx.ap.beacon = new;
7574
7575 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
7576 }
7577
7578 EXIT();
7579 return status;
7580}
7581
7582static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
7583 struct net_device *dev,
7584 struct beacon_parameters *params)
7585{
7586 int ret;
7587
7588 vos_ssr_protect(__func__);
7589 ret = __wlan_hdd_cfg80211_set_beacon(wiphy, dev, params);
7590 vos_ssr_unprotect(__func__);
7591
7592 return ret;
7593}
7594
7595#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7596
7597#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7598static int __wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
7599 struct net_device *dev)
7600#else
7601static int __wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
7602 struct net_device *dev)
7603#endif
7604{
7605 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7606 hdd_context_t *pHddCtx = NULL;
7607 hdd_scaninfo_t *pScanInfo = NULL;
7608 VOS_STATUS status;
7609 long ret;
7610
7611 ENTER();
7612
7613 if (NULL == pAdapter)
7614 {
7615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7616 "%s: HDD adapter context is Null", __func__);
7617 return -ENODEV;
7618 }
7619
7620 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7621 TRACE_CODE_HDD_CFG80211_STOP_AP,
7622 pAdapter->sessionId, pAdapter->device_mode));
7623 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7624 status = wlan_hdd_validate_context(pHddCtx);
7625 if (0 != status)
7626 {
7627 return status;
7628 }
7629
7630 pScanInfo = &pHddCtx->scan_info;
7631
7632 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
7633 __func__, hdd_device_modetoString(pAdapter->device_mode),
7634 pAdapter->device_mode);
7635
7636 ret = wlan_hdd_scan_abort(pAdapter);
7637
7638 if (ret < 0)
7639 {
7640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7641 FL("Timeout occurred while waiting for abortscan %ld"), ret);
7642
7643 if (pHddCtx->isLogpInProgress)
7644 {
7645 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7646 "%s: LOGP in Progress. Ignore!!!", __func__);
7647
7648 VOS_ASSERT(pScanInfo->mScanPending);
7649 return -EAGAIN;
7650 }
7651 VOS_ASSERT(pScanInfo->mScanPending);
7652 }
7653
7654 /* Delete all associated STAs before stopping AP/P2P GO */
7655 hdd_del_all_sta(pAdapter);
7656 hdd_hostapd_stop(dev);
7657
7658 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
7659 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
7660 )
7661 {
7662 beacon_data_t *old;
7663
7664 old = pAdapter->sessionCtx.ap.beacon;
7665
7666 if (!old)
7667 {
7668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7669 FL("session(%d) beacon data points to NULL"),
7670 pAdapter->sessionId);
7671 return -ENOENT;
7672 }
7673
7674 hdd_cleanup_actionframe(pHddCtx, pAdapter);
7675
7676 mutex_lock(&pHddCtx->sap_lock);
7677 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7678 {
7679 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
7680 {
7681 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7682
7683 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
7684
7685 if (!VOS_IS_STATUS_SUCCESS(status))
7686 {
7687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7688 ("ERROR: HDD vos wait for single_event failed!!"));
7689 VOS_ASSERT(0);
7690 }
7691 }
7692 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
7693 /* BSS stopped, clear the active sessions for this device mode */
7694 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7695 }
7696 mutex_unlock(&pHddCtx->sap_lock);
7697
7698 if(status != VOS_STATUS_SUCCESS)
7699 {
7700 hddLog(VOS_TRACE_LEVEL_FATAL,
7701 "%s:Error!!! Stopping the BSS",__func__);
7702 return -EINVAL;
7703 }
7704
7705 if (ccmCfgSetInt(pHddCtx->hHal,
7706 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
7707 ==eHAL_STATUS_FAILURE)
7708 {
7709 hddLog(LOGE,
7710 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
7711 }
7712
7713 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
7714 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7715 eANI_BOOLEAN_FALSE) )
7716 {
7717 hddLog(LOGE,
7718 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7719 }
7720
7721 // Reset WNI_CFG_PROBE_RSP Flags
7722 wlan_hdd_reset_prob_rspies(pAdapter);
7723
7724 pAdapter->sessionCtx.ap.beacon = NULL;
7725 kfree(old);
7726#ifdef WLAN_FEATURE_P2P_DEBUG
7727 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
7728 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
7729 {
7730 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
7731 "GO got removed");
7732 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
7733 }
7734#endif
7735 }
7736 EXIT();
7737 return status;
7738}
7739
7740#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7741static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
7742 struct net_device *dev)
7743{
7744 int ret;
7745
7746 vos_ssr_protect(__func__);
7747 ret = __wlan_hdd_cfg80211_del_beacon(wiphy, dev);
7748 vos_ssr_unprotect(__func__);
7749
7750 return ret;
7751}
7752#else
7753static int wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
7754 struct net_device *dev)
7755{
7756 int ret;
7757
7758 vos_ssr_protect(__func__);
7759 ret = __wlan_hdd_cfg80211_stop_ap(wiphy, dev);
7760 vos_ssr_unprotect(__func__);
7761
7762 return ret;
7763}
7764#endif
7765
7766#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
7767
7768static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
7769 struct net_device *dev,
7770 struct cfg80211_ap_settings *params)
7771{
7772 hdd_adapter_t *pAdapter;
7773 hdd_context_t *pHddCtx;
7774 int status;
7775
7776 ENTER();
7777
7778 if (NULL == dev || NULL == params)
7779 {
7780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7781 "%s: Device or params is Null", __func__);
7782 return -ENODEV;
7783 }
7784
7785 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7786 if (NULL == pAdapter)
7787 {
7788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7789 "%s: HDD adapter is Null", __func__);
7790 return -ENODEV;
7791 }
7792
7793 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7794 TRACE_CODE_HDD_CFG80211_START_AP, pAdapter->sessionId,
7795 params-> beacon_interval));
7796 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7797 {
7798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7799 "%s: HDD adapter magic is invalid", __func__);
7800 return -ENODEV;
7801 }
7802
7803 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7804 status = wlan_hdd_validate_context(pHddCtx);
7805 if (0 != status)
7806 {
7807 return status;
7808 }
7809
7810 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %s (%d)",
7811 __func__, hdd_device_modetoString(pAdapter->device_mode),
7812 pAdapter->device_mode);
7813
7814 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
7815 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
7816 )
7817 {
7818 beacon_data_t *old, *new;
7819
7820 old = pAdapter->sessionCtx.ap.beacon;
7821
7822 if (old)
7823 {
7824 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
7825 FL("already beacon info added to session(%d)"),
7826 pAdapter->sessionId);
7827 return -EALREADY;
7828 }
7829
7830#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
7831 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,
7832 &new,
7833 &params->beacon);
7834#else
7835 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,
7836 &new,
7837 &params->beacon,
7838 params->dtim_period);
7839#endif
7840
7841 if (status != 0)
7842 {
7843 hddLog(VOS_TRACE_LEVEL_FATAL,
7844 "%s:Error!!! Allocating the new beacon", __func__);
7845 return -EINVAL;
7846 }
7847 pAdapter->sessionCtx.ap.beacon = new;
7848#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7849 wlan_hdd_cfg80211_set_channel(wiphy, dev,
7850#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
7851 params->channel, params->channel_type);
7852#else
7853 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
7854#endif
7855#endif
7856 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
7857 params->ssid_len, params->hidden_ssid,
7858 params->auth_type);
7859 }
7860
7861 EXIT();
7862 return status;
7863}
7864
7865static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
7866 struct net_device *dev,
7867 struct cfg80211_ap_settings *params)
7868{
7869 int ret;
7870
7871 vos_ssr_protect(__func__);
7872 ret = __wlan_hdd_cfg80211_start_ap(wiphy, dev, params);
7873 vos_ssr_unprotect(__func__);
7874
7875 return ret;
7876}
7877
7878static int __wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
7879 struct net_device *dev,
7880 struct cfg80211_beacon_data *params)
7881{
7882 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7883 hdd_context_t *pHddCtx;
7884 int status;
7885
7886 ENTER();
7887
7888 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7889 TRACE_CODE_HDD_CFG80211_CHANGE_BEACON,
7890 pAdapter->sessionId, pAdapter->device_mode));
7891 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
7892 __func__, pAdapter->device_mode);
7893
7894 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7895 status = wlan_hdd_validate_context(pHddCtx);
7896 if (0 != status)
7897 {
7898 return status;
7899 }
7900
7901 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
7902 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
7903 )
7904 {
7905 beacon_data_t *old,*new;
7906
7907 old = pAdapter->sessionCtx.ap.beacon;
7908
7909 if (!old)
7910 {
7911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7912 FL("session(%d) beacon data points to NULL"),
7913 pAdapter->sessionId);
7914 return -ENOENT;
7915 }
7916
7917 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
7918
7919 if(status != VOS_STATUS_SUCCESS) {
7920 hddLog(VOS_TRACE_LEVEL_FATAL,
7921 "%s: Error!!! Allocating the new beacon",__func__);
7922 return -EINVAL;
7923 }
7924
7925 pAdapter->sessionCtx.ap.beacon = new;
7926
7927 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0,
7928 pAdapter->sessionCtx.ap.sapConfig.authType);
7929 }
7930
7931 EXIT();
7932 return status;
7933}
7934
7935static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
7936 struct net_device *dev,
7937 struct cfg80211_beacon_data *params)
7938{
7939 int ret;
7940
7941 vos_ssr_protect(__func__);
7942 ret = __wlan_hdd_cfg80211_change_beacon(wiphy, dev, params);
7943 vos_ssr_unprotect(__func__);
7944
7945 return ret;
7946}
7947
7948#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
7949
7950static int __wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
7951 struct net_device *dev,
7952 struct bss_parameters *params)
7953{
7954 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7955 hdd_context_t *pHddCtx;
7956 int ret = 0;
7957
7958 ENTER();
7959
7960 if (NULL == pAdapter)
7961 {
7962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7963 "%s: HDD adapter is Null", __func__);
7964 return -ENODEV;
7965 }
7966 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7967 ret = wlan_hdd_validate_context(pHddCtx);
7968 if (0 != ret)
7969 {
7970 return ret;
7971 }
7972 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7973 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
7974 pAdapter->sessionId, params->ap_isolate));
7975 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
7976 __func__, hdd_device_modetoString(pAdapter->device_mode),
7977 pAdapter->device_mode);
7978
7979 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
7980 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
7981 )
7982 {
7983 /* ap_isolate == -1 means that in change bss, upper layer doesn't
7984 * want to update this parameter */
7985 if (-1 != params->ap_isolate)
7986 {
7987 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
7988 }
7989 }
7990
7991 EXIT();
7992 return 0;
7993}
7994
7995static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
7996 struct net_device *dev,
7997 struct bss_parameters *params)
7998{
7999 int ret;
8000
8001 vos_ssr_protect(__func__);
8002 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
8003 vos_ssr_unprotect(__func__);
8004
8005 return ret;
8006}
8007/* FUNCTION: wlan_hdd_change_country_code_cd
8008* to wait for contry code completion
8009*/
8010void* wlan_hdd_change_country_code_cb(void *pAdapter)
8011{
8012 hdd_adapter_t *call_back_pAdapter = pAdapter;
8013 complete(&call_back_pAdapter->change_country_code);
8014 return NULL;
8015}
8016
8017/*
8018 * FUNCTION: __wlan_hdd_cfg80211_change_iface
8019 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
8020 */
8021int __wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
8022 struct net_device *ndev,
8023 enum nl80211_iftype type,
8024 u32 *flags,
8025 struct vif_params *params
8026 )
8027{
8028 struct wireless_dev *wdev;
8029 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
8030 hdd_context_t *pHddCtx;
8031 hdd_adapter_t *pP2pAdapter = NULL;
8032 tCsrRoamProfile *pRoamProfile = NULL;
8033 eCsrRoamBssType LastBSSType;
8034 hdd_config_t *pConfig = NULL;
8035 eMib_dot11DesiredBssType connectedBssType;
8036 VOS_STATUS status;
8037 long ret;
8038
8039 ENTER();
8040
8041 if (!pAdapter)
8042 {
8043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8044 "%s: Adapter context is null", __func__);
8045 return VOS_STATUS_E_FAILURE;
8046 }
8047
8048 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8049 if (!pHddCtx)
8050 {
8051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8052 "%s: HDD context is null", __func__);
8053 return VOS_STATUS_E_FAILURE;
8054 }
8055
8056 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
8057 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
8058 pAdapter->sessionId, type));
8059 status = wlan_hdd_validate_context(pHddCtx);
8060 if (0 != status)
8061 {
8062 return status;
8063 }
8064
8065 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
8066 __func__, hdd_device_modetoString(pAdapter->device_mode),
8067 pAdapter->device_mode);
8068
8069 if (vos_max_concurrent_connections_reached()) {
8070 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
8071 return -EINVAL;
8072 }
8073 pConfig = pHddCtx->cfg_ini;
8074 wdev = ndev->ieee80211_ptr;
8075
8076#ifdef WLAN_BTAMP_FEATURE
8077 if((NL80211_IFTYPE_P2P_CLIENT == type)||
8078 (NL80211_IFTYPE_ADHOC == type)||
8079 (NL80211_IFTYPE_AP == type)||
8080 (NL80211_IFTYPE_P2P_GO == type))
8081 {
8082 pHddCtx->isAmpAllowed = VOS_FALSE;
8083 // stop AMP traffic
8084 status = WLANBAP_StopAmp();
8085 if(VOS_STATUS_SUCCESS != status )
8086 {
8087 pHddCtx->isAmpAllowed = VOS_TRUE;
8088 hddLog(VOS_TRACE_LEVEL_FATAL,
8089 "%s: Failed to stop AMP", __func__);
8090 return -EINVAL;
8091 }
8092 }
8093#endif //WLAN_BTAMP_FEATURE
8094 /* Reset the current device mode bit mask*/
8095 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
8096
8097 if ((pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) &&
8098 ((type == NL80211_IFTYPE_P2P_CLIENT) ||
8099 (type == NL80211_IFTYPE_P2P_GO)))
8100 {
8101 /* Notify Mode change in case of concurrency.
8102 * Below function invokes TDLS teardown Functionality Since TDLS is
8103 * not Supported in case of concurrency i.e Once P2P session
8104 * is detected disable offchannel and teardown TDLS links
8105 */
8106 hddLog(LOG1,
8107 FL("Device mode = %d Interface type = %d"),
8108 pAdapter->device_mode, type);
8109 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
8110 }
8111
8112 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8113 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
8114 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8115 )
8116 {
8117 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8118 if (!pWextState)
8119 {
8120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8121 "%s: pWextState is null", __func__);
8122 return VOS_STATUS_E_FAILURE;
8123 }
8124 pRoamProfile = &pWextState->roamProfile;
8125 LastBSSType = pRoamProfile->BSSType;
8126
8127 switch (type)
8128 {
8129 case NL80211_IFTYPE_STATION:
8130 case NL80211_IFTYPE_P2P_CLIENT:
8131 hddLog(VOS_TRACE_LEVEL_INFO,
8132 "%s: setting interface Type to INFRASTRUCTURE", __func__);
8133 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
8134#ifdef WLAN_FEATURE_11AC
8135 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
8136 {
8137 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
8138 }
8139#endif
8140 pRoamProfile->phyMode =
8141 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
8142 wdev->iftype = type;
8143 //Check for sub-string p2p to confirm its a p2p interface
8144 if (NULL != strstr(ndev->name,"p2p"))
8145 {
8146#ifdef FEATURE_WLAN_TDLS
8147 mutex_lock(&pHddCtx->tdls_lock);
8148 wlan_hdd_tdls_exit(pAdapter, TRUE);
8149 mutex_unlock(&pHddCtx->tdls_lock);
8150#endif
8151 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
8152 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
8153 }
8154 else
8155 {
8156 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
8157 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
8158 }
8159 break;
8160
8161 case NL80211_IFTYPE_ADHOC:
8162 hddLog(VOS_TRACE_LEVEL_INFO,
8163 "%s: setting interface Type to ADHOC", __func__);
8164 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
8165 pRoamProfile->phyMode =
8166 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
8167 pAdapter->device_mode = WLAN_HDD_IBSS;
8168 wdev->iftype = type;
8169 hdd_set_ibss_ops( pAdapter );
8170 hdd_ibss_init_tx_rx( pAdapter );
8171
8172 status = hdd_sta_id_hash_attach(pAdapter);
8173 if (VOS_STATUS_SUCCESS != status) {
8174 hddLog(VOS_TRACE_LEVEL_ERROR,
8175 FL("Failed to initialize hash for IBSS"));
8176 }
8177 break;
8178
8179 case NL80211_IFTYPE_AP:
8180 case NL80211_IFTYPE_P2P_GO:
8181 {
8182 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
8183 "%s: setting interface Type to %s", __func__,
8184 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
8185
8186 //Cancel any remain on channel for GO mode
8187 if (NL80211_IFTYPE_P2P_GO == type)
8188 {
8189 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
8190 }
8191 if (NL80211_IFTYPE_AP == type)
8192 {
8193 /* As Loading WLAN Driver one interface being created for p2p device
8194 * address. This will take one HW STA and the max number of clients
8195 * that can connect to softAP will be reduced by one. so while changing
8196 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
8197 * interface as it is not required in SoftAP mode.
8198 */
8199
8200 // Get P2P Adapter
8201 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
8202
8203 if (pP2pAdapter)
8204 {
8205 hdd_stop_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
8206 hdd_deinit_adapter(pHddCtx, pP2pAdapter, TRUE);
8207 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
8208 }
8209 }
8210 //Disable IMPS & BMPS for SAP/GO
8211 if(VOS_STATUS_E_FAILURE ==
8212 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
8213 {
8214 //Fail to Exit BMPS
8215 VOS_ASSERT(0);
8216 }
8217
8218 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
8219
8220#ifdef FEATURE_WLAN_TDLS
8221
8222 /* A Mutex Lock is introduced while changing the mode to
8223 * protect the concurrent access for the Adapters by TDLS
8224 * module.
8225 */
8226 mutex_lock(&pHddCtx->tdls_lock);
8227#endif
8228 //De-init the adapter.
8229 hdd_deinit_adapter( pHddCtx, pAdapter, TRUE);
8230 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
8231 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
8232 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
8233#ifdef FEATURE_WLAN_TDLS
8234 mutex_unlock(&pHddCtx->tdls_lock);
8235#endif
8236 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
8237 (pConfig->apRandomBssidEnabled))
8238 {
8239 /* To meet Android requirements create a randomized
8240 MAC address of the form 02:1A:11:Fx:xx:xx */
8241 get_random_bytes(&ndev->dev_addr[3], 3);
8242 ndev->dev_addr[0] = 0x02;
8243 ndev->dev_addr[1] = 0x1A;
8244 ndev->dev_addr[2] = 0x11;
8245 ndev->dev_addr[3] |= 0xF0;
8246 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
8247 VOS_MAC_ADDR_SIZE);
8248 pr_info("wlan: Generated HotSpot BSSID " MAC_ADDRESS_STR"\n",
8249 MAC_ADDR_ARRAY(ndev->dev_addr));
8250 }
8251
8252 hdd_set_ap_ops( pAdapter->dev );
8253
8254 /* This is for only SAP mode where users can
8255 * control country through ini.
8256 * P2P GO follows station country code
8257 * acquired during the STA scanning. */
8258 if((NL80211_IFTYPE_AP == type) &&
8259 (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0))
8260 {
8261 int status = 0;
8262 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
8263 "%s: setting country code from INI ", __func__);
8264 init_completion(&pAdapter->change_country_code);
8265 status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
8266 (void *)(tSmeChangeCountryCallback)
8267 wlan_hdd_change_country_code_cb,
8268 pConfig->apCntryCode, pAdapter,
8269 pHddCtx->pvosContext,
8270 eSIR_FALSE,
8271 eSIR_TRUE);
8272 if (eHAL_STATUS_SUCCESS == status)
8273 {
8274 /* Wait for completion */
8275 ret = wait_for_completion_interruptible_timeout(
8276 &pAdapter->change_country_code,
8277 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8278 if (ret <= 0)
8279 {
8280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8281 FL("SME Timed out while setting country code %ld"),
8282 ret);
8283
8284 if (pHddCtx->isLogpInProgress)
8285 {
8286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8287 "%s: LOGP in Progress. Ignore!!!", __func__);
8288 return -EAGAIN;
8289 }
8290 }
8291 }
8292 else
8293 {
8294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8295 "%s: SME Change Country code failed",__func__);
8296 return -EINVAL;
8297 }
8298 }
8299 status = hdd_init_ap_mode(pAdapter);
8300 if(status != VOS_STATUS_SUCCESS)
8301 {
8302 hddLog(VOS_TRACE_LEVEL_FATAL,
8303 "%s: Error initializing the ap mode", __func__);
8304 return -EINVAL;
8305 }
8306 hdd_set_conparam(1);
8307
8308 status = hdd_sta_id_hash_attach(pAdapter);
8309 if (VOS_STATUS_SUCCESS != status)
8310 {
8311 hddLog(VOS_TRACE_LEVEL_ERROR,
8312 FL("Failed to initialize hash for AP"));
8313 return -EINVAL;
8314 }
8315
8316 /*interface type changed update in wiphy structure*/
8317 if(wdev)
8318 {
8319 wdev->iftype = type;
8320 pHddCtx->change_iface = type;
8321 }
8322 else
8323 {
8324 hddLog(VOS_TRACE_LEVEL_ERROR,
8325 "%s: ERROR !!!! Wireless dev is NULL", __func__);
8326 return -EINVAL;
8327 }
8328 goto done;
8329 }
8330
8331 default:
8332 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
8333 __func__);
8334 return -EOPNOTSUPP;
8335 }
8336 }
8337 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
8338 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
8339 )
8340 {
8341 switch(type)
8342 {
8343 case NL80211_IFTYPE_STATION:
8344 case NL80211_IFTYPE_P2P_CLIENT:
8345 case NL80211_IFTYPE_ADHOC:
8346
8347 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
8348#ifdef FEATURE_WLAN_TDLS
8349
8350 /* A Mutex Lock is introduced while changing the mode to
8351 * protect the concurrent access for the Adapters by TDLS
8352 * module.
8353 */
8354 mutex_lock(&pHddCtx->tdls_lock);
8355#endif
8356 hdd_deinit_adapter( pHddCtx, pAdapter, TRUE);
8357 wdev->iftype = type;
8358 //Check for sub-string p2p to confirm its a p2p interface
8359 if (NULL != strstr(ndev->name,"p2p"))
8360 {
8361 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
8362 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
8363 }
8364 else
8365 {
8366 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
8367 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
8368 }
8369 hdd_set_conparam(0);
8370 pHddCtx->change_iface = type;
8371 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
8372 hdd_set_station_ops( pAdapter->dev );
8373#ifdef FEATURE_WLAN_TDLS
8374 mutex_unlock(&pHddCtx->tdls_lock);
8375#endif
8376 status = hdd_init_station_mode( pAdapter );
8377 if( VOS_STATUS_SUCCESS != status )
8378 return -EOPNOTSUPP;
8379 /* In case of JB, for P2P-GO, only change interface will be called,
8380 * This is the right place to enable back bmps_imps()
8381 */
8382 if (pHddCtx->hdd_wlan_suspended)
8383 {
8384 hdd_set_pwrparams(pHddCtx);
8385 }
8386 hdd_enable_bmps_imps(pHddCtx);
8387 goto done;
8388 case NL80211_IFTYPE_AP:
8389 case NL80211_IFTYPE_P2P_GO:
8390 wdev->iftype = type;
8391 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
8392 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
8393 goto done;
8394 default:
8395 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
8396 __func__);
8397 return -EOPNOTSUPP;
8398
8399 }
8400
8401 }
8402 else
8403 {
8404 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: unsupported device mode(%s (%d))",
8405 __func__, hdd_device_modetoString(pAdapter->device_mode),
8406 pAdapter->device_mode);
8407 return -EOPNOTSUPP;
8408 }
8409
8410
8411 if(pRoamProfile)
8412 {
8413 if ( LastBSSType != pRoamProfile->BSSType )
8414 {
8415 /*interface type changed update in wiphy structure*/
8416 wdev->iftype = type;
8417
8418 /*the BSS mode changed, We need to issue disconnect
8419 if connected or in IBSS disconnect state*/
8420 if ( hdd_connGetConnectedBssType(
8421 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
8422 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
8423 {
8424 /*need to issue a disconnect to CSR.*/
8425 INIT_COMPLETION(pAdapter->disconnect_comp_var);
8426 if( eHAL_STATUS_SUCCESS ==
8427 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
8428 pAdapter->sessionId,
8429 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
8430 {
8431 ret = wait_for_completion_interruptible_timeout(
8432 &pAdapter->disconnect_comp_var,
8433 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
8434 if (ret <= 0)
8435 {
8436 hddLog(VOS_TRACE_LEVEL_ERROR,
8437 FL("wait on disconnect_comp_var failed %ld"), ret);
8438 }
8439 }
8440 }
8441 }
8442 }
8443
8444done:
8445 /*set bitmask based on updated value*/
8446 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
8447
8448 /* Only STA mode support TM now
8449 * all other mode, TM feature should be disabled */
8450 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
8451 (~VOS_STA & pHddCtx->concurrency_mode) )
8452 {
8453 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
8454 }
8455
8456#ifdef WLAN_BTAMP_FEATURE
8457 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
8458 (pHddCtx->no_of_open_sessions[WLAN_HDD_INFRA_STATION] <=1))
8459 {
8460 //we are ok to do AMP
8461 pHddCtx->isAmpAllowed = VOS_TRUE;
8462 }
8463#endif //WLAN_BTAMP_FEATURE
8464 EXIT();
8465 return 0;
8466}
8467
8468/*
8469 * FUNCTION: wlan_hdd_cfg80211_change_iface
8470 * wrapper function to protect the actual implementation from SSR.
8471 */
8472int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
8473 struct net_device *ndev,
8474 enum nl80211_iftype type,
8475 u32 *flags,
8476 struct vif_params *params
8477 )
8478{
8479 int ret;
8480
8481 vos_ssr_protect(__func__);
8482 ret = __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
8483 vos_ssr_unprotect(__func__);
8484
8485 return ret;
8486}
8487
8488#ifdef FEATURE_WLAN_TDLS
8489static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
8490 struct net_device *dev,
8491#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
8492 const u8 *mac,
8493#else
8494 u8 *mac,
8495#endif
8496 bool update, tCsrStaParams *StaParams)
8497{
8498 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8499 hddTdlsPeer_t *pTdlsPeer;
8500 long ret;
8501 tANI_U16 numCurrTdlsPeers;
8502 hdd_adapter_t *pAdapter;
8503 VOS_STATUS status;
8504
8505 ENTER();
8506
8507 if (!dev) {
8508 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Dev pointer is NULL"));
8509 return -EINVAL;
8510 }
8511
8512 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8513 if (!pAdapter) {
8514 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adapter is NULL"));
8515 return -EINVAL;
8516 }
8517
8518 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
8519 {
8520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8521 "Invalid arguments");
8522 return -EINVAL;
8523 }
8524
8525 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
8526 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
8527 {
8528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8529 "%s: TDLS mode is disabled OR not enabled in FW."
8530 MAC_ADDRESS_STR " Request declined.",
8531 __func__, MAC_ADDR_ARRAY(mac));
8532 return -ENOTSUPP;
8533 }
8534
8535 if (pHddCtx->isLogpInProgress)
8536 {
8537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8538 "%s:LOGP in Progress. Ignore!!!", __func__);
8539 wlan_hdd_tdls_set_link_status(pAdapter,
8540 mac,
8541 eTDLS_LINK_IDLE,
8542 eTDLS_LINK_UNSPECIFIED);
8543 return -EBUSY;
8544 }
8545
8546 mutex_lock(&pHddCtx->tdls_lock);
8547 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac);
8548
8549 if ( NULL == pTdlsPeer ) {
8550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8551 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
8552 __func__, MAC_ADDR_ARRAY(mac), update);
8553 mutex_unlock(&pHddCtx->tdls_lock);
8554 return -EINVAL;
8555 }
8556
8557 /* in add station, we accept existing valid staId if there is */
8558 if ((0 == update) &&
8559 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
8560 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
8561 {
8562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8563 "%s: " MAC_ADDRESS_STR
8564 " link_status %d. staId %d. add station ignored.",
8565 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
8566 mutex_unlock(&pHddCtx->tdls_lock);
8567 return 0;
8568 }
8569 /* in change station, we accept only when staId is valid */
8570 if ((1 == update) &&
8571 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
8572 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
8573 {
8574 tANI_U16 staId = pTdlsPeer->staId;
8575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8576 "%s: " MAC_ADDRESS_STR
8577 " link status %d. staId %d. change station %s.",
8578 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, staId,
8579 (TDLS_STA_INDEX_VALID(staId)) ? "ignored" : "declined");
8580 mutex_unlock(&pHddCtx->tdls_lock);
8581 return (TDLS_STA_INDEX_VALID(staId)) ? 0 : -EPERM;
8582 }
8583 mutex_unlock(&pHddCtx->tdls_lock);
8584
8585 /* when others are on-going, we want to change link_status to idle */
8586 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE))
8587 {
8588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8589 "%s: " MAC_ADDRESS_STR
8590 " TDLS setup is ongoing. Request declined.",
8591 __func__, MAC_ADDR_ARRAY(mac));
8592 goto error;
8593 }
8594
8595 /* first to check if we reached to maximum supported TDLS peer.
8596 TODO: for now, return -EPERM looks working fine,
8597 but need to check if any other errno fit into this category.*/
8598 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
8599 if (HDD_MAX_NUM_TDLS_STA <= numCurrTdlsPeers)
8600 {
8601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8602 "%s: " MAC_ADDRESS_STR
8603 " TDLS Max peer already connected. Request declined."
8604 " Num of peers (%d), Max allowed (%d).",
8605 __func__, MAC_ADDR_ARRAY(mac), numCurrTdlsPeers,
8606 HDD_MAX_NUM_TDLS_STA);
8607 goto error;
8608 }
8609 else
8610 {
8611 hddTdlsPeer_t *pTdlsPeer;
8612 mutex_lock(&pHddCtx->tdls_lock);
8613 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, FALSE);
8614 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
8615 {
8616 mutex_unlock(&pHddCtx->tdls_lock);
8617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8618 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
8619 __func__, MAC_ADDR_ARRAY(mac));
8620 return -EPERM;
8621 }
8622 mutex_unlock(&pHddCtx->tdls_lock);
8623 }
8624 if (0 == update)
8625 wlan_hdd_tdls_set_link_status(pAdapter,
8626 mac,
8627 eTDLS_LINK_CONNECTING,
8628 eTDLS_LINK_SUCCESS);
8629
8630 /* debug code */
8631 if (NULL != StaParams)
8632 {
8633 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8634 "%s: TDLS Peer Parameters.", __func__);
8635 if(StaParams->htcap_present)
8636 {
8637 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8638 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
8639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8640 "ht_capa->extended_capabilities: %0x",
8641 StaParams->HTCap.extendedHtCapInfo);
8642 }
8643 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8644 "params->capability: %0x",StaParams->capability);
8645 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8646 "params->ext_capab_len: %0x",StaParams->extn_capability[0]);
8647 if(StaParams->vhtcap_present)
8648 {
8649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8650 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
8651 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
8652 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
8653 }
8654 {
8655 int i = 0;
8656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
8657 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
8658 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8659 "[%d]: %x ", i, StaParams->supported_rates[i]);
8660 }
8661 } /* end debug code */
8662 else if ((1 == update) && (NULL == StaParams))
8663 {
8664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8665 "%s : update is true, but staParams is NULL. Error!", __func__);
8666 return -EPERM;
8667 }
8668
8669 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
8670
8671 if (!update)
8672 {
8673 /*Before adding sta make sure that device exited from BMPS*/
8674 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
8675 {
8676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8677 "%s: Adding tdls peer sta. Disable BMPS", __func__);
8678 status = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
8679 if (status != VOS_STATUS_SUCCESS) {
8680 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set BMPS/IMPS"));
8681 }
8682 }
8683
8684 ret = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
8685 pAdapter->sessionId, mac);
8686 if (ret != eHAL_STATUS_SUCCESS) {
8687 hddLog(VOS_TRACE_LEVEL_ERROR,
8688 FL("Failed to add TDLS peer STA. Enable Bmps"));
8689 wlan_hdd_tdls_check_bmps(pAdapter);
8690 return -EPERM;
8691 }
8692 }
8693 else
8694 {
8695 ret = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
8696 pAdapter->sessionId, mac, StaParams);
8697 if (ret != eHAL_STATUS_SUCCESS) {
8698 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to change TDLS peer STA params"));
8699 return -EPERM;
8700 }
8701 }
8702
8703 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
8704 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
8705
8706 if (ret <= 0)
8707 {
8708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8709 "%s: timeout waiting for tdls add station indication %ld",
8710 __func__, ret);
8711 return -EPERM;
8712 }
8713
8714 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
8715 {
8716 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8717 "%s: Add Station is unsucessful", __func__);
8718 return -EPERM;
8719 }
8720
8721 return 0;
8722
8723error:
8724 wlan_hdd_tdls_set_link_status(pAdapter,
8725 mac,
8726 eTDLS_LINK_IDLE,
8727 eTDLS_LINK_UNSPECIFIED);
8728 return -EPERM;
8729
8730}
8731#endif
8732
8733static int __wlan_hdd_change_station(struct wiphy *wiphy,
8734 struct net_device *dev,
8735#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
8736 const u8 *mac,
8737#else
8738 u8 *mac,
8739#endif
8740 struct station_parameters *params)
8741{
8742 VOS_STATUS status = VOS_STATUS_SUCCESS;
8743 hdd_adapter_t *pAdapter;
8744 hdd_context_t *pHddCtx;
8745 hdd_station_ctx_t *pHddStaCtx;
8746 v_MACADDR_t STAMacAddress;
8747 int ret = 0;
8748#ifdef FEATURE_WLAN_TDLS
8749 tCsrStaParams StaParams = {0};
8750 tANI_U8 isBufSta = 0;
8751 tANI_U8 isOffChannelSupported = 0;
8752#endif
8753
8754 ENTER();
8755
8756 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8757 if ((NULL == pAdapter))
8758 {
8759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8760 "invalid adapter ");
8761 return -EINVAL;
8762 }
8763
8764 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
8765 TRACE_CODE_HDD_CHANGE_STATION,
8766 pAdapter->sessionId, params->listen_interval));
8767 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8768
8769 ret = wlan_hdd_validate_context(pHddCtx);
8770 if (0 != ret)
8771 {
8772 return ret;
8773 }
8774
8775 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8776
8777 if (NULL == pHddStaCtx)
8778 {
8779 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8780 "invalid HDD station context");
8781 return -EINVAL;
8782 }
8783 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
8784
8785 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
8786 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
8787 {
8788 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
8789 {
8790 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
8791 WLANTL_STA_AUTHENTICATED);
8792
8793 if (status != VOS_STATUS_SUCCESS)
8794 {
8795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8796 "%s: Not able to change TL state to AUTHENTICATED", __func__);
8797 return -EINVAL;
8798 }
8799 }
8800 }
8801 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8802 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
8803#ifdef FEATURE_WLAN_TDLS
8804 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
8805 StaParams.capability = params->capability;
8806 StaParams.uapsd_queues = params->uapsd_queues;
8807 StaParams.max_sp = params->max_sp;
8808
8809 /* Convert (first channel , number of channels) tuple to
8810 * the total list of channels. This goes with the assumption
8811 * that if the first channel is < 14, then the next channels
8812 * are an incremental of 1 else an incremental of 4 till the number
8813 * of channels.
8814 */
8815 if (0 != params->supported_channels_len) {
8816 int i = 0,j = 0,k = 0, no_of_channels = 0 ;
8817 for ( i = 0 ; i < params->supported_channels_len ; i+=2)
8818 {
8819 int wifi_chan_index;
8820 StaParams.supported_channels[j] = params->supported_channels[i];
8821 wifi_chan_index =
8822 ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 );
8823 no_of_channels = params->supported_channels[i+1];
8824 for(k=1; k <= no_of_channels; k++)
8825 {
8826 StaParams.supported_channels[j+1] =
8827 StaParams.supported_channels[j] + wifi_chan_index;
8828 j+=1;
8829 }
8830 }
8831 StaParams.supported_channels_len = j;
8832 }
SaidiReddy Yenuga02105d32017-02-14 16:00:57 +05308833 if (params->supported_oper_classes_len >
8834 SIR_MAC_MAX_SUPP_OPER_CLASSES) {
8835 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8836 "received oper classes:%d, resetting it to max supported %d",
8837 params->supported_oper_classes_len,
8838 SIR_MAC_MAX_SUPP_OPER_CLASSES);
8839 params->supported_oper_classes_len =
8840 SIR_MAC_MAX_SUPP_OPER_CLASSES;
8841 }
chrmhoffmannbb97ca42017-05-13 21:27:44 +02008842 vos_mem_copy(StaParams.supported_oper_classes,
8843 params->supported_oper_classes,
8844 params->supported_oper_classes_len);
8845 StaParams.supported_oper_classes_len =
8846 params->supported_oper_classes_len;
8847
Gururaj Patil6b8abb32019-09-23 13:48:29 +00008848 if (params->ext_capab_len > sizeof(StaParams.extn_capability)) {
8849 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8850 "received extn capabilities: %d, reset to max supported",
8851 params->ext_capab_len);
8852 params->ext_capab_len = sizeof(StaParams.extn_capability);
8853 }
8854
chrmhoffmannbb97ca42017-05-13 21:27:44 +02008855 if (0 != params->ext_capab_len)
8856 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
Gururaj Patil6b8abb32019-09-23 13:48:29 +00008857 params->ext_capab_len);
chrmhoffmannbb97ca42017-05-13 21:27:44 +02008858
8859 if (NULL != params->ht_capa)
8860 {
8861 StaParams.htcap_present = 1;
8862 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
8863 }
8864
8865 StaParams.supported_rates_len = params->supported_rates_len;
8866
8867 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
8868 * The supported_rates array , for all the structures propogating till Add Sta
8869 * to the firmware has to be modified , if the supplicant (ieee80211) is
8870 * modified to send more rates.
8871 */
8872
8873 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
8874 */
8875 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
8876 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
8877
8878 if (0 != StaParams.supported_rates_len) {
8879 int i = 0;
8880 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
8881 StaParams.supported_rates_len);
8882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8883 "Supported Rates with Length %d", StaParams.supported_rates_len);
8884 for (i=0; i < StaParams.supported_rates_len; i++)
8885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8886 "[%d]: %0x", i, StaParams.supported_rates[i]);
8887 }
8888
8889 if (NULL != params->vht_capa)
8890 {
8891 StaParams.vhtcap_present = 1;
8892 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
8893 }
8894
8895 if (0 != params->ext_capab_len ) {
8896 /*Define A Macro : TODO Sunil*/
8897 if ((1<<4) & StaParams.extn_capability[3]) {
8898 isBufSta = 1;
8899 }
8900 /* TDLS Channel Switching Support */
8901 if ((1<<6) & StaParams.extn_capability[3]) {
8902 isOffChannelSupported = 1;
8903 }
8904 }
8905 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac,
8906 &StaParams, isBufSta,
Gururaj Patil6b8abb32019-09-23 13:48:29 +00008907 isOffChannelSupported);
chrmhoffmannbb97ca42017-05-13 21:27:44 +02008908
8909 if (VOS_STATUS_SUCCESS != status) {
8910 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8911 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
8912 return -EINVAL;
8913 }
8914 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
8915
8916 if (VOS_STATUS_SUCCESS != status) {
8917 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8918 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
8919 return -EINVAL;
8920 }
8921 }
8922#endif
8923 }
8924 EXIT();
8925 return status;
8926}
8927
8928#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
8929static int wlan_hdd_change_station(struct wiphy *wiphy,
8930 struct net_device *dev,
8931 const u8 *mac,
8932 struct station_parameters *params)
8933#else
8934static int wlan_hdd_change_station(struct wiphy *wiphy,
8935 struct net_device *dev,
8936 u8 *mac,
8937 struct station_parameters *params)
8938#endif
8939{
8940 int ret;
8941
8942 vos_ssr_protect(__func__);
8943 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
8944 vos_ssr_unprotect(__func__);
8945
8946 return ret;
8947}
8948
8949/*
8950 * FUNCTION: __wlan_hdd_cfg80211_add_key
8951 * This function is used to initialize the key information
8952 */
8953#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
8954static int __wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
8955 struct net_device *ndev,
8956 u8 key_index, bool pairwise,
8957 const u8 *mac_addr,
8958 struct key_params *params
8959 )
8960#else
8961static int __wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
8962 struct net_device *ndev,
8963 u8 key_index, const u8 *mac_addr,
8964 struct key_params *params
8965 )
8966#endif
8967{
8968 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
8969 tCsrRoamSetKey setKey;
8970 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
8971 int status;
8972 v_U32_t roamId= 0xFF;
8973 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8974 hdd_hostapd_state_t *pHostapdState;
8975 VOS_STATUS vos_status;
8976 eHalStatus halStatus;
8977 hdd_context_t *pHddCtx;
8978
8979 ENTER();
8980
8981 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
8982 TRACE_CODE_HDD_CFG80211_ADD_KEY,
8983 pAdapter->sessionId, params->key_len));
8984 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8985 status = wlan_hdd_validate_context(pHddCtx);
8986 if (0 != status)
8987 {
8988 return status;
8989 }
8990
8991 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
8992 __func__, hdd_device_modetoString(pAdapter->device_mode),
8993 pAdapter->device_mode);
8994
8995 if (CSR_MAX_NUM_KEY <= key_index)
8996 {
8997 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
8998 key_index);
8999
9000 return -EINVAL;
9001 }
9002
9003 if (CSR_MAX_KEY_LEN < params->key_len)
9004 {
9005 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
9006 params->key_len);
9007
9008 return -EINVAL;
9009 }
9010
Jingxiang Geb0fb2972017-10-26 16:44:00 +08009011 if (CSR_MAX_RSC_LEN < params->seq_len)
9012 {
9013 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Invalid seq length %d", __func__,
9014 params->seq_len);
Ashish Kumar Dhanotiya72924cc2017-12-08 14:50:46 +05309015
9016 return -EINVAL;
Jingxiang Geb0fb2972017-10-26 16:44:00 +08009017 }
9018
chrmhoffmannbb97ca42017-05-13 21:27:44 +02009019 hddLog(VOS_TRACE_LEVEL_INFO,
Jingxiang Geb0fb2972017-10-26 16:44:00 +08009020 "%s: called with key index = %d & key length %d & seq length %d",
9021 __func__, key_index, params->key_len, params->seq_len);
chrmhoffmannbb97ca42017-05-13 21:27:44 +02009022
9023 /*extract key idx, key len and key*/
9024 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
9025 setKey.keyId = key_index;
9026 setKey.keyLength = params->key_len;
9027 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
Jingxiang Geb0fb2972017-10-26 16:44:00 +08009028 vos_mem_copy(&setKey.keyRsc[0], params->seq, params->seq_len);
chrmhoffmannbb97ca42017-05-13 21:27:44 +02009029
9030 switch (params->cipher)
9031 {
9032 case WLAN_CIPHER_SUITE_WEP40:
9033 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9034 break;
9035
9036 case WLAN_CIPHER_SUITE_WEP104:
9037 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9038 break;
9039
9040 case WLAN_CIPHER_SUITE_TKIP:
9041 {
9042 u8 *pKey = &setKey.Key[0];
9043 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9044
9045 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
9046
9047 /*Supplicant sends the 32bytes key in this order
9048
9049 |--------------|----------|----------|
9050 | Tk1 |TX-MIC | RX Mic |
9051 |--------------|----------|----------|
9052 <---16bytes---><--8bytes--><--8bytes-->
9053
9054 */
9055 /*Sme expects the 32 bytes key to be in the below order
9056
9057 |--------------|----------|----------|
9058 | Tk1 |RX-MIC | TX Mic |
9059 |--------------|----------|----------|
9060 <---16bytes---><--8bytes--><--8bytes-->
9061 */
9062 /* Copy the Temporal Key 1 (TK1) */
9063 vos_mem_copy(pKey, params->key, 16);
9064
9065 /*Copy the rx mic first*/
9066 vos_mem_copy(&pKey[16], &params->key[24], 8);
9067
9068 /*Copy the tx mic */
9069 vos_mem_copy(&pKey[24], &params->key[16], 8);
9070
9071
9072 break;
9073 }
9074
9075 case WLAN_CIPHER_SUITE_CCMP:
9076 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9077 break;
9078
9079#ifdef FEATURE_WLAN_WAPI
9080 case WLAN_CIPHER_SUITE_SMS4:
9081 {
9082 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
9083 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
9084 params->key, params->key_len);
9085 return 0;
9086 }
9087#endif
9088
9089#ifdef FEATURE_WLAN_ESE
9090 case WLAN_CIPHER_SUITE_KRK:
9091 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9092 break;
9093#endif
9094
9095#ifdef WLAN_FEATURE_11W
9096 case WLAN_CIPHER_SUITE_AES_CMAC:
9097 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9098 break;
9099#endif
9100
9101 default:
9102 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
9103 __func__, params->cipher);
9104 status = -EOPNOTSUPP;
9105 goto end;
9106 }
9107
9108 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
9109 __func__, setKey.encType);
9110
9111 if (
9112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9113 (!pairwise)
9114#else
9115 (!mac_addr || is_broadcast_ether_addr(mac_addr))
9116#endif
9117 )
9118 {
9119 /* set group key*/
9120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9121 "%s- %d: setting Broadcast key",
9122 __func__, __LINE__);
9123 setKey.keyDirection = eSIR_RX_ONLY;
9124 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
9125 }
9126 else
9127 {
9128 /* set pairwise key*/
9129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9130 "%s- %d: setting pairwise key",
9131 __func__, __LINE__);
9132 setKey.keyDirection = eSIR_TX_RX;
9133 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
9134 }
9135 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
9136 {
9137 setKey.keyDirection = eSIR_TX_RX;
9138 /*Set the group key*/
9139 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
9140 pAdapter->sessionId, &setKey, &roamId );
9141
9142 if ( 0 != status )
9143 {
9144 hddLog(VOS_TRACE_LEVEL_ERROR,
9145 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
9146 status = -EINVAL;
9147 goto end;
9148 }
9149 /*Save the keys here and call sme_RoamSetKey for setting
9150 the PTK after peer joins the IBSS network*/
9151 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
9152 &setKey, sizeof(tCsrRoamSetKey));
9153 goto end;
9154 }
9155 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
9156 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
9157 {
9158 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9159 if( pHostapdState->bssState == BSS_START )
9160 {
9161 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9162 vos_status = wlan_hdd_check_ula_done(pAdapter);
9163
9164 if ( vos_status != VOS_STATUS_SUCCESS )
9165 {
9166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9167 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
9168 __LINE__, vos_status );
9169
9170 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9171
9172 status = -EINVAL;
9173 goto end;
9174 }
9175
9176 status = WLANSAP_SetKeySta( pVosContext, &setKey);
9177
9178 if ( status != eHAL_STATUS_SUCCESS )
9179 {
9180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9181 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
9182 __LINE__, status );
9183 status = -EINVAL;
9184 goto end;
9185 }
9186 }
9187
9188 /* Saving WEP keys */
9189 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
9190 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
9191 {
9192 //Save the wep key in ap context. Issue setkey after the BSS is started.
9193 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9194 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
9195 }
9196 else
9197 {
9198 //Save the key in ap context. Issue setkey after the BSS is started.
9199 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9200 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
9201 }
9202 }
9203 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
9204 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
9205 {
9206 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9207 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9208
9209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9210 if (!pairwise)
9211#else
9212 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
9213#endif
9214 {
9215 /* set group key*/
9216 if (pHddStaCtx->roam_info.deferKeyComplete)
9217 {
9218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9219 "%s- %d: Perform Set key Complete",
9220 __func__, __LINE__);
9221 hdd_PerformRoamSetKeyComplete(pAdapter);
9222 }
9223 }
9224
9225 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
9226
9227 pWextState->roamProfile.Keys.defaultIndex = key_index;
9228
9229
9230 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
9231 params->key, params->key_len);
9232
9233
9234 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9235
9236 hddLog(VOS_TRACE_LEVEL_INFO_MED,
9237 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
9238 __func__, setKey.peerMac[0], setKey.peerMac[1],
9239 setKey.peerMac[2], setKey.peerMac[3],
9240 setKey.peerMac[4], setKey.peerMac[5],
9241 setKey.keyDirection);
9242
9243 vos_status = wlan_hdd_check_ula_done(pAdapter);
9244
9245 if ( vos_status != VOS_STATUS_SUCCESS )
9246 {
9247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9248 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
9249 __LINE__, vos_status );
9250
9251 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9252
9253 status = -EINVAL;
9254 goto end;
9255
9256 }
9257
9258#ifdef WLAN_FEATURE_VOWIFI_11R
9259 /* The supplicant may attempt to set the PTK once pre-authentication
9260 is done. Save the key in the UMAC and include it in the ADD BSS
9261 request */
9262 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
9263 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
9264 {
9265 hddLog(VOS_TRACE_LEVEL_INFO_MED,
9266 "%s: Update PreAuth Key success", __func__);
9267 status = 0;
9268 goto end;
9269 }
9270 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
9271 {
9272 hddLog(VOS_TRACE_LEVEL_ERROR,
9273 "%s: Update PreAuth Key failed", __func__);
9274 status = -EINVAL;
9275 goto end;
9276 }
9277#endif /* WLAN_FEATURE_VOWIFI_11R */
9278
9279 /* issue set key request to SME*/
9280 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
9281 pAdapter->sessionId, &setKey, &roamId );
9282
9283 if ( 0 != status )
9284 {
9285 hddLog(VOS_TRACE_LEVEL_ERROR,
9286 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
9287 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9288 status = -EINVAL;
9289 goto end;
9290 }
9291
9292
9293 /* in case of IBSS as there was no information available about WEP keys during
9294 * IBSS join, group key intialized with NULL key, so re-initialize group key
9295 * with correct value*/
9296 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
9297 !( ( IW_AUTH_KEY_MGMT_802_1X
9298 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
9299 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
9300 )
9301 &&
9302 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
9303 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
9304 )
9305 )
9306 {
9307 setKey.keyDirection = eSIR_RX_ONLY;
9308 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
9309
9310 hddLog(VOS_TRACE_LEVEL_INFO_MED,
9311 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
9312 __func__, setKey.peerMac[0], setKey.peerMac[1],
9313 setKey.peerMac[2], setKey.peerMac[3],
9314 setKey.peerMac[4], setKey.peerMac[5],
9315 setKey.keyDirection);
9316
9317 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
9318 pAdapter->sessionId, &setKey, &roamId );
9319
9320 if ( 0 != status )
9321 {
9322 hddLog(VOS_TRACE_LEVEL_ERROR,
9323 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
9324 __func__, status);
9325 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9326 status = -EINVAL;
9327 goto end;
9328 }
9329 }
9330 }
9331
9332end:
9333 /* Need to clear any trace of key value in the memory.
9334 * Thus zero out the memory even though it is local
9335 * variable.
9336 */
9337 vos_mem_zero(&setKey, sizeof(setKey));
9338 EXIT();
9339 return status;
9340}
9341
9342#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9343static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
9344 struct net_device *ndev,
9345 u8 key_index, bool pairwise,
9346 const u8 *mac_addr,
9347 struct key_params *params
9348 )
9349#else
9350static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
9351 struct net_device *ndev,
9352 u8 key_index, const u8 *mac_addr,
9353 struct key_params *params
9354 )
9355#endif
9356{
9357 int ret;
9358 vos_ssr_protect(__func__);
9359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9360 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
9361 mac_addr, params);
9362#else
9363 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, mac_addr,
9364 params);
9365#endif
9366 vos_ssr_unprotect(__func__);
9367
9368 return ret;
9369}
9370
9371/*
9372 * FUNCTION: __wlan_hdd_cfg80211_get_key
9373 * This function is used to get the key information
9374 */
9375#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9376static int __wlan_hdd_cfg80211_get_key(
9377 struct wiphy *wiphy,
9378 struct net_device *ndev,
9379 u8 key_index, bool pairwise,
9380 const u8 *mac_addr, void *cookie,
9381 void (*callback)(void *cookie, struct key_params*)
9382 )
9383#else
9384static int __wlan_hdd_cfg80211_get_key(
9385 struct wiphy *wiphy,
9386 struct net_device *ndev,
9387 u8 key_index, const u8 *mac_addr, void *cookie,
9388 void (*callback)(void *cookie, struct key_params*)
9389 )
9390#endif
9391{
9392 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
9393 hdd_wext_state_t *pWextState = NULL;
9394 tCsrRoamProfile *pRoamProfile = NULL;
9395 struct key_params params;
9396 hdd_context_t *pHddCtx;
9397 int ret = 0;
9398
9399 ENTER();
9400
9401 if (NULL == pAdapter)
9402 {
9403 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9404 "%s: HDD adapter is Null", __func__);
9405 return -ENODEV;
9406 }
9407
9408 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9409 ret = wlan_hdd_validate_context(pHddCtx);
9410 if (0 != ret)
9411 {
9412 return ret;
9413 }
9414
9415 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9416 pRoamProfile = &(pWextState->roamProfile);
9417
9418 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
9419 __func__, hdd_device_modetoString(pAdapter->device_mode),
9420 pAdapter->device_mode);
9421
9422 memset(&params, 0, sizeof(params));
9423
9424 if (CSR_MAX_NUM_KEY <= key_index)
9425 {
9426 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid key index %d"), key_index);
9427 return -EINVAL;
9428 }
9429
9430 switch(pRoamProfile->EncryptionType.encryptionType[0])
9431 {
9432 case eCSR_ENCRYPT_TYPE_NONE:
9433 params.cipher = IW_AUTH_CIPHER_NONE;
9434 break;
9435
9436 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
9437 case eCSR_ENCRYPT_TYPE_WEP40:
9438 params.cipher = WLAN_CIPHER_SUITE_WEP40;
9439 break;
9440
9441 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
9442 case eCSR_ENCRYPT_TYPE_WEP104:
9443 params.cipher = WLAN_CIPHER_SUITE_WEP104;
9444 break;
9445
9446 case eCSR_ENCRYPT_TYPE_TKIP:
9447 params.cipher = WLAN_CIPHER_SUITE_TKIP;
9448 break;
9449
9450 case eCSR_ENCRYPT_TYPE_AES:
9451 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
9452 break;
9453
9454 default:
9455 params.cipher = IW_AUTH_CIPHER_NONE;
9456 break;
9457 }
9458
9459 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
9460 TRACE_CODE_HDD_CFG80211_GET_KEY,
9461 pAdapter->sessionId, params.cipher));
9462
9463 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
9464 params.seq_len = 0;
9465 params.seq = NULL;
9466 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
9467 callback(cookie, &params);
9468 EXIT();
9469 return 0;
9470}
9471
9472#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9473static int wlan_hdd_cfg80211_get_key(
9474 struct wiphy *wiphy,
9475 struct net_device *ndev,
9476 u8 key_index, bool pairwise,
9477 const u8 *mac_addr, void *cookie,
9478 void (*callback)(void *cookie, struct key_params*)
9479 )
9480#else
9481static int wlan_hdd_cfg80211_get_key(
9482 struct wiphy *wiphy,
9483 struct net_device *ndev,
9484 u8 key_index, const u8 *mac_addr, void *cookie,
9485 void (*callback)(void *cookie, struct key_params*)
9486 )
9487#endif
9488{
9489 int ret;
9490
9491 vos_ssr_protect(__func__);
9492#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9493 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
9494 mac_addr, cookie, callback);
9495#else
9496 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, mac_addr,
9497 callback);
9498#endif
9499 vos_ssr_unprotect(__func__);
9500
9501 return ret;
9502}
9503
9504/*
9505 * FUNCTION: __wlan_hdd_cfg80211_del_key
9506 * This function is used to delete the key information
9507 */
9508#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9509static int __wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
9510 struct net_device *ndev,
9511 u8 key_index,
9512 bool pairwise,
9513 const u8 *mac_addr
9514 )
9515#else
9516static int __wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
9517 struct net_device *ndev,
9518 u8 key_index,
9519 const u8 *mac_addr
9520 )
9521#endif
9522{
9523 int status = 0;
9524
9525 //This code needs to be revisited. There is sme_removeKey API, we should
9526 //plan to use that. After the change to use correct index in setkey,
9527 //it is observed that this is invalidating peer
9528 //key index whenever re-key is done. This is affecting data link.
9529 //It should be ok to ignore del_key.
9530#if 0
9531 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
9532 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9533 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
9534 tCsrRoamSetKey setKey;
9535 v_U32_t roamId= 0xFF;
9536
9537 ENTER();
9538
9539 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
9540 __func__,pAdapter->device_mode);
9541
9542 if (CSR_MAX_NUM_KEY <= key_index)
9543 {
9544 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
9545 key_index);
9546
9547 return -EINVAL;
9548 }
9549
9550 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
9551 setKey.keyId = key_index;
9552
9553 if (mac_addr)
9554 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
9555 else
9556 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
9557
9558 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
9559
9560 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9561 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9562 )
9563 {
9564
9565 hdd_hostapd_state_t *pHostapdState =
9566 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9567 if( pHostapdState->bssState == BSS_START)
9568 {
9569 status = WLANSAP_SetKeySta( pVosContext, &setKey);
9570
9571 if ( status != eHAL_STATUS_SUCCESS )
9572 {
9573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9574 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
9575 __LINE__, status );
9576 }
9577 }
9578 }
9579 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
9580 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
9581 )
9582 {
9583 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9584
9585 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9586
9587 hddLog(VOS_TRACE_LEVEL_INFO_MED,
9588 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
9589 __func__, setKey.peerMac[0], setKey.peerMac[1],
9590 setKey.peerMac[2], setKey.peerMac[3],
9591 setKey.peerMac[4], setKey.peerMac[5]);
9592 if(pAdapter->sessionCtx.station.conn_info.connState ==
9593 eConnectionState_Associated)
9594 {
9595 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
9596 pAdapter->sessionId, &setKey, &roamId );
9597
9598 if ( 0 != status )
9599 {
9600 hddLog(VOS_TRACE_LEVEL_ERROR,
9601 "%s: sme_RoamSetKey failure, returned %d",
9602 __func__, status);
9603 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9604 return -EINVAL;
9605 }
9606 }
9607 }
9608#endif
9609 EXIT();
9610 return status;
9611}
9612
9613#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9614static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
9615 struct net_device *ndev,
9616 u8 key_index,
9617 bool pairwise,
9618 const u8 *mac_addr
9619 )
9620#else
9621static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
9622 struct net_device *ndev,
9623 u8 key_index,
9624 const u8 *mac_addr
9625 )
9626#endif
9627{
9628 int ret;
9629
9630 vos_ssr_protect(__func__);
9631#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9632 ret = __wlan_hdd_cfg80211_del_key(wiphy, ndev, key_index, pairwise,
9633 mac_addr);
9634#else
9635 ret = __wlan_hdd_cfg80211_del_key(wiphy, ndev, key_index, mac_addr);
9636#endif
9637 vos_ssr_unprotect(__func__);
9638
9639 return ret;
9640}
9641
9642/*
9643 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
9644 * This function is used to set the default tx key index
9645 */
9646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9647static int __wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
9648 struct net_device *ndev,
9649 u8 key_index,
9650 bool unicast, bool multicast)
9651#else
9652static int __wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
9653 struct net_device *ndev,
9654 u8 key_index)
9655#endif
9656{
9657 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
9658 int status;
9659 hdd_wext_state_t *pWextState;
9660 hdd_station_ctx_t *pHddStaCtx;
9661 hdd_context_t *pHddCtx;
9662
9663 ENTER();
9664
9665 if ((NULL == pAdapter))
9666 {
9667 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9668 "invalid adapter");
9669 return -EINVAL;
9670 }
9671
9672 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
9673 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
9674 pAdapter->sessionId, key_index));
9675
9676 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9677 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9678
9679 if ((NULL == pWextState) || (NULL == pHddStaCtx))
9680 {
9681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9682 "invalid Wext state or HDD context");
9683 return -EINVAL;
9684 }
9685
9686 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d",
9687 __func__,pAdapter->device_mode, key_index);
9688
9689 if (CSR_MAX_NUM_KEY <= key_index)
9690 {
9691 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
9692 key_index);
9693
9694 return -EINVAL;
9695 }
9696
9697 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9698 status = wlan_hdd_validate_context(pHddCtx);
9699 if (0 != status)
9700 {
9701 return status;
9702 }
9703
9704 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
9705 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
9706 )
9707 {
9708 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
9709 pHddStaCtx->conn_info.ucEncryptionType) &&
9710 (eCSR_ENCRYPT_TYPE_AES !=
9711 pHddStaCtx->conn_info.ucEncryptionType)
9712 )
9713 {
9714 /* if default key index is not same as previous one,
9715 * then update the default key index */
9716
9717 tCsrRoamSetKey setKey;
9718 v_U32_t roamId= 0xFF;
9719 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
9720
9721 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
9722 __func__, key_index);
9723
9724 Keys->defaultIndex = (u8)key_index;
9725 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
9726 setKey.keyId = key_index;
9727 setKey.keyLength = Keys->KeyLength[key_index];
9728
9729 vos_mem_copy(&setKey.Key[0],
9730 &Keys->KeyMaterial[key_index][0],
9731 Keys->KeyLength[key_index]);
9732
9733 setKey.keyDirection = eSIR_TX_RX;
9734
9735 vos_mem_copy(setKey.peerMac,
9736 &pHddStaCtx->conn_info.bssId[0],
9737 WNI_CFG_BSSID_LEN);
9738
9739 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
9740 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
9741 eCSR_ENCRYPT_TYPE_WEP104)
9742 {
9743 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
9744 even though ap is configured for WEP-40 encryption. In this canse the key length
9745 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
9746 type(104) and switching encryption type to 40*/
9747 pWextState->roamProfile.EncryptionType.encryptionType[0] =
9748 eCSR_ENCRYPT_TYPE_WEP40;
9749 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
9750 eCSR_ENCRYPT_TYPE_WEP40;
9751 }
9752
9753 setKey.encType =
9754 pWextState->roamProfile.EncryptionType.encryptionType[0];
9755
9756 /* issue set key request */
9757 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
9758 pAdapter->sessionId, &setKey, &roamId );
9759
9760 if ( 0 != status )
9761 {
9762 hddLog(VOS_TRACE_LEVEL_ERROR,
9763 "%s: sme_RoamSetKey failed, returned %d", __func__,
9764 status);
9765 return -EINVAL;
9766 }
9767 }
9768 }
9769
9770 /* In SoftAp mode setting key direction for default mode */
9771 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
9772 {
9773 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
9774 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
9775 (eCSR_ENCRYPT_TYPE_AES !=
9776 pWextState->roamProfile.EncryptionType.encryptionType[0])
9777 )
9778 {
9779 /* Saving key direction for default key index to TX default */
9780 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9781 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
9782 }
9783 }
9784 EXIT();
9785 return status;
9786}
9787
9788#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9789static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
9790 struct net_device *ndev,
9791 u8 key_index,
9792 bool unicast, bool multicast)
9793#else
9794static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
9795 struct net_device *ndev,
9796 u8 key_index)
9797#endif
9798{
9799 int ret;
9800 vos_ssr_protect(__func__);
9801#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
9802 ret = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
9803 multicast);
9804#else
9805 ret = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index);
9806#endif
9807 vos_ssr_unprotect(__func__);
9808
9809 return ret;
9810}
9811
9812/*
9813 * FUNCTION: wlan_hdd_cfg80211_inform_bss
9814 * This function is used to inform the BSS details to nl80211 interface.
9815 */
9816static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
9817 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
9818{
9819 struct net_device *dev = pAdapter->dev;
9820 struct wireless_dev *wdev = dev->ieee80211_ptr;
9821 struct wiphy *wiphy = wdev->wiphy;
9822 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
9823 int chan_no;
9824 int ie_length;
9825 const char *ie;
9826 unsigned int freq;
9827 struct ieee80211_channel *chan;
9828 int rssi = 0;
9829 struct cfg80211_bss *bss = NULL;
9830
9831 if( NULL == pBssDesc )
9832 {
9833 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL", __func__);
9834 return bss;
9835 }
9836
9837 chan_no = pBssDesc->channelId;
9838 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
9839 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
9840
9841 if( NULL == ie )
9842 {
9843 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL", __func__);
9844 return bss;
9845 }
9846
9847#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
9848 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
9849 {
9850 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
9851 }
9852 else
9853 {
9854 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
9855 }
9856#else
9857 freq = ieee80211_channel_to_frequency(chan_no);
9858#endif
9859
9860 chan = __ieee80211_get_channel(wiphy, freq);
9861
9862 if (!chan) {
9863 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
9864 return NULL;
9865 }
9866
9867 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
9868
9869 return cfg80211_inform_bss(wiphy, chan,
9870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
9871 CFG80211_BSS_FTYPE_UNKNOWN,
9872#endif
9873 pBssDesc->bssId,
9874 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
9875 pBssDesc->capabilityInfo,
9876 pBssDesc->beaconInterval, ie, ie_length,
9877 rssi, GFP_KERNEL );
9878}
9879
9880
9881
9882/*
9883 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
9884 * This function is used to inform the BSS details to nl80211 interface.
9885 */
9886struct cfg80211_bss*
9887wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
9888 tSirBssDescription *bss_desc
9889 )
9890{
9891 /*
9892 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
9893 already exists in bss data base of cfg80211 for that particular BSS ID.
9894 Using cfg80211_inform_bss_frame to update the bss entry instead of
9895 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
9896 now there is no possibility to get the mgmt(probe response) frame from PE,
9897 converting bss_desc to ieee80211_mgmt(probe response) and passing to
9898 cfg80211_inform_bss_frame.
9899 */
9900 struct net_device *dev = pAdapter->dev;
9901 struct wireless_dev *wdev = dev->ieee80211_ptr;
9902 struct wiphy *wiphy = wdev->wiphy;
9903 int chan_no = bss_desc->channelId;
9904#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
9905 qcom_ie_age *qie_age = NULL;
9906 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
9907#else
9908 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
9909#endif
9910 const char *ie =
9911 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
9912 unsigned int freq;
9913 struct ieee80211_channel *chan;
9914 struct ieee80211_mgmt *mgmt = NULL;
9915 struct cfg80211_bss *bss_status = NULL;
9916 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
9917 int rssi = 0;
9918 hdd_context_t *pHddCtx;
9919 int status;
9920#ifdef WLAN_OPEN_SOURCE
9921 struct timespec ts;
9922#endif
9923
9924
9925 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9926 status = wlan_hdd_validate_context(pHddCtx);
9927 if (0 != status)
9928 {
9929 return NULL;
9930 }
9931
9932 mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
9933 if (!mgmt)
9934 {
9935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9936 "%s: memory allocation failed ", __func__);
9937 return NULL;
9938 }
9939
9940 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
9941
9942#ifdef WLAN_OPEN_SOURCE
9943 /* Android does not want the timestamp from the frame.
9944 Instead it wants a monotonic increasing value */
9945 get_monotonic_boottime(&ts);
9946 mgmt->u.probe_resp.timestamp =
9947 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
9948#else
9949 /* keep old behavior for non-open source (for now) */
9950 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
9951 sizeof (bss_desc->timeStamp));
9952
9953#endif
9954
9955 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
9956 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
9957
9958#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
9959 /* GPS Requirement: need age ie per entry. Using vendor specific. */
9960 /* Assuming this is the last IE, copy at the end */
9961 ie_length -=sizeof(qcom_ie_age);
9962 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
9963 qie_age->element_id = QCOM_VENDOR_IE_ID;
9964 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
9965 qie_age->oui_1 = QCOM_OUI1;
9966 qie_age->oui_2 = QCOM_OUI2;
9967 qie_age->oui_3 = QCOM_OUI3;
9968 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
9969 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
9970#endif
9971
9972 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
9973 if (bss_desc->fProbeRsp)
9974 {
9975 mgmt->frame_control |=
9976 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
9977 }
9978 else
9979 {
9980 mgmt->frame_control |=
9981 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
9982 }
9983
9984#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
9985 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
9986 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
9987 {
9988 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
9989 }
9990 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
9991 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
9992
9993 {
9994 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
9995 }
9996 else
9997 {
9998 hddLog(VOS_TRACE_LEVEL_ERROR, "%s Invalid chan_no:%d",
9999 __func__, chan_no);
10000 kfree(mgmt);
10001 return NULL;
10002 }
10003#else
10004 freq = ieee80211_channel_to_frequency(chan_no);
10005#endif
10006 chan = __ieee80211_get_channel(wiphy, freq);
10007 /*when the band is changed on the fly using the GUI, three things are done
10008 * 1. scan abort 2.flush scan results from cache 3.update the band with the new band user specified(refer to the hdd_setBand_helper function)
10009 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
10010 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
10011 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
10012 * and discards the channels correponding to previous band and calls back with zero bss results.
10013 * but if the time between band update and scan done callback is very small then band change will not reflect in SME and SME reports to HDD
10014 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
10015 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
10016 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
10017 * So drop the bss and continue to next bss.
10018 */
10019 if(chan == NULL)
10020 {
10021 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
10022 kfree(mgmt);
10023 return NULL;
10024 }
10025 /*To keep the rssi icon of the connected AP in the scan window
10026 *and the rssi icon of the wireless networks in sync
10027 * */
10028 if (( eConnectionState_Associated ==
10029 pAdapter->sessionCtx.station.conn_info.connState ) &&
10030 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
10031 pAdapter->sessionCtx.station.conn_info.bssId,
10032 WNI_CFG_BSSID_LEN)) &&
10033 (pHddCtx->hdd_wlan_suspended == FALSE))
10034 {
10035 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
10036 rssi = (pAdapter->rssi * 100);
10037 }
10038 else
10039 {
10040 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
10041 }
10042
10043 hddLog(VOS_TRACE_LEVEL_INFO, "%s: BSSID:" MAC_ADDRESS_STR " Channel:%d"
10044 " RSSI:%d", __func__, MAC_ADDR_ARRAY(mgmt->bssid),
10045 vos_freq_to_chan(chan->center_freq), (int)(rssi/100));
10046
10047 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
10048 frame_len, rssi, GFP_KERNEL);
10049 kfree(mgmt);
10050 return bss_status;
10051}
10052
10053/*
10054 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
10055 * This function is used to update the BSS data base of CFG8011
10056 */
10057struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
10058 tCsrRoamInfo *pRoamInfo
10059 )
10060{
10061 tCsrRoamConnectedProfile roamProfile;
10062 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10063 struct cfg80211_bss *bss = NULL;
10064
10065 ENTER();
10066
10067 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10068 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
10069
10070 if (NULL != roamProfile.pBssDesc)
10071 {
10072 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10073 roamProfile.pBssDesc);
10074
10075 if (NULL == bss)
10076 {
10077 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
10078 __func__);
10079 }
10080
10081 sme_RoamFreeConnectProfile(hHal, &roamProfile);
10082 }
10083 else
10084 {
10085 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
10086 __func__);
10087 }
10088 return bss;
10089}
10090
10091/*
10092 * FUNCTION: wlan_hdd_cfg80211_update_bss
10093 */
10094static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
10095 hdd_adapter_t *pAdapter
10096 )
10097{
10098 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10099 tCsrScanResultInfo *pScanResult;
10100 eHalStatus status = 0;
10101 tScanResultHandle pResult;
10102 struct cfg80211_bss *bss_status = NULL;
10103 hdd_context_t *pHddCtx;
10104 bool is_p2p_scan = false;
10105 ENTER();
10106
10107 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10108 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10109 NO_SESSION, pAdapter->sessionId));
10110
10111 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10112
10113 if (pHddCtx->isLogpInProgress)
10114 {
10115 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10116 "%s:LOGP in Progress. Ignore!!!",__func__);
10117 return -EAGAIN;
10118 }
10119
10120
10121 /*bss_update is not allowed during wlan driver loading or unloading*/
10122 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
10123 {
10124 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10125 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
10126 return VOS_STATUS_E_PERM;
10127 }
10128
10129 if (pAdapter->request != NULL)
10130 {
10131 if ((pAdapter->request->n_ssids == 1)
10132 && (pAdapter->request->ssids != NULL)
10133 && vos_mem_compare(&pAdapter->request->ssids[0], "DIRECT-", 7))
10134 is_p2p_scan = true;
10135 }
10136 /*
10137 * start getting scan results and populate cgf80211 BSS database
10138 */
10139 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
10140
10141 /* no scan results */
10142 if (NULL == pResult)
10143 {
10144 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result Status %d",
10145 __func__, status);
10146 wlan_hdd_get_frame_logs(pAdapter,
10147 WLAN_HDD_GET_FRAME_LOG_CMD_SEND_AND_CLEAR);
10148 return status;
10149 }
10150
10151 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
10152
10153 while (pScanResult)
10154 {
10155 /*
10156 * cfg80211_inform_bss() is not updating ie field of bss entry, if
10157 * entry already exists in bss data base of cfg80211 for that
10158 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
10159 * bss entry instead of cfg80211_inform_bss, But this call expects
10160 * mgmt packet as input. As of now there is no possibility to get
10161 * the mgmt(probe response) frame from PE, converting bss_desc to
10162 * ieee80211_mgmt(probe response) and passing to c
10163 * fg80211_inform_bss_frame.
10164 * */
10165 if(is_p2p_scan && (pScanResult->ssId.ssId != NULL) &&
10166 !vos_mem_compare( pScanResult->ssId.ssId, "DIRECT-", 7) )
10167 {
10168 pScanResult = sme_ScanResultGetNext(hHal, pResult);
10169 continue; //Skip the non p2p bss entries
10170 }
10171 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10172 &pScanResult->BssDescriptor);
10173
10174
10175 if (NULL == bss_status)
10176 {
10177 hddLog(VOS_TRACE_LEVEL_INFO,
10178 "%s: NULL returned by cfg80211_inform_bss", __func__);
10179 }
10180 else
10181 {
10182 cfg80211_put_bss(
10183#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
10184 wiphy,
10185#endif
10186 bss_status);
10187 }
10188
10189 pScanResult = sme_ScanResultGetNext(hHal, pResult);
10190 }
10191
10192 sme_ScanResultPurge(hHal, pResult);
10193 is_p2p_scan = false;
10194 return 0;
10195}
10196
10197void
10198hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
10199{
10200 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
10201 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
10202} /****** end hddPrintMacAddr() ******/
10203
10204void
10205hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
10206{
10207 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
10208 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
10209 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
10210 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
10211 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
10212} /****** end hddPrintPmkId() ******/
10213
10214//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
10215//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
10216
10217//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
10218//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
10219
10220#define dump_bssid(bssid) \
10221 { \
10222 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
10223 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
10224 }
10225
10226#define dump_pmkid(pMac, pmkid) \
10227 { \
10228 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
10229 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
10230 }
10231
10232#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
10233/*
10234 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
10235 * This function is used to notify the supplicant of a new PMKSA candidate.
10236 */
10237int wlan_hdd_cfg80211_pmksa_candidate_notify(
10238 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
10239 int index, bool preauth )
10240{
10241#ifdef FEATURE_WLAN_OKC
10242 struct net_device *dev = pAdapter->dev;
10243 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
10244
10245 ENTER();
10246 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
10247
10248 if( NULL == pRoamInfo )
10249 {
10250 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL", __func__);
10251 return -EINVAL;
10252 }
10253
10254 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
10255 {
10256 dump_bssid(pRoamInfo->bssid);
10257 cfg80211_pmksa_candidate_notify(dev, index,
10258 pRoamInfo->bssid, preauth, GFP_KERNEL);
10259 }
10260#endif /* FEATURE_WLAN_OKC */
10261 return 0;
10262}
10263#endif //FEATURE_WLAN_LFR
10264
10265#ifdef FEATURE_WLAN_LFR_METRICS
10266/*
10267 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth
10268 * 802.11r/LFR metrics reporting function to report preauth initiation
10269 *
10270 */
10271#define MAX_LFR_METRICS_EVENT_LENGTH 100
10272VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
10273 tCsrRoamInfo *pRoamInfo)
10274{
10275 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10276 union iwreq_data wrqu;
10277
10278 ENTER();
10279
10280 if (NULL == pAdapter)
10281 {
10282 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
10283 return VOS_STATUS_E_FAILURE;
10284 }
10285
10286 /* create the event */
10287 memset(&wrqu, 0, sizeof(wrqu));
10288 memset(metrics_notification, 0, sizeof(metrics_notification));
10289
10290 wrqu.data.pointer = metrics_notification;
10291 wrqu.data.length = scnprintf(metrics_notification,
10292 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT "
10293 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
10294
10295 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
10296
10297 EXIT();
10298
10299 return VOS_STATUS_SUCCESS;
10300}
10301
10302/*
10303 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status
10304 * 802.11r/LFR metrics reporting function to report preauth completion
10305 * or failure
10306 */
10307VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(
10308 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status)
10309{
10310 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10311 union iwreq_data wrqu;
10312
10313 ENTER();
10314
10315 if (NULL == pAdapter)
10316 {
10317 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
10318 return VOS_STATUS_E_FAILURE;
10319 }
10320
10321 /* create the event */
10322 memset(&wrqu, 0, sizeof(wrqu));
10323 memset(metrics_notification, 0, sizeof(metrics_notification));
10324
10325 scnprintf(metrics_notification, sizeof(metrics_notification),
10326 "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR,
10327 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10328
10329 if (1 == preauth_status)
10330 strncat(metrics_notification, " TRUE", 5);
10331 else
10332 strncat(metrics_notification, " FALSE", 6);
10333
10334 wrqu.data.pointer = metrics_notification;
10335 wrqu.data.length = strlen(metrics_notification);
10336
10337 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
10338
10339 EXIT();
10340
10341 return VOS_STATUS_SUCCESS;
10342}
10343
10344/*
10345 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover
10346 * 802.11r/LFR metrics reporting function to report handover initiation
10347 *
10348 */
10349VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter,
10350 tCsrRoamInfo *pRoamInfo)
10351{
10352 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10353 union iwreq_data wrqu;
10354
10355 ENTER();
10356
10357 if (NULL == pAdapter)
10358 {
10359 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
10360 return VOS_STATUS_E_FAILURE;
10361 }
10362
10363 /* create the event */
10364 memset(&wrqu, 0, sizeof(wrqu));
10365 memset(metrics_notification, 0, sizeof(metrics_notification));
10366
10367 wrqu.data.pointer = metrics_notification;
10368 wrqu.data.length = scnprintf(metrics_notification,
10369 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER "
10370 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
10371
10372 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
10373
10374 EXIT();
10375
10376 return VOS_STATUS_SUCCESS;
10377}
10378#endif
10379
10380/*
10381 * FUNCTION: hdd_cfg80211_scan_done_callback
10382 * scanning callback function, called after finishing scan
10383 *
10384 */
10385static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
10386 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
10387{
10388 struct net_device *dev = (struct net_device *) pContext;
10389 //struct wireless_dev *wdev = dev->ieee80211_ptr;
10390 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
10391 hdd_scaninfo_t *pScanInfo;
10392 struct cfg80211_scan_request *req = NULL;
10393 int ret = 0;
10394 bool aborted = false;
10395 long waitRet = 0;
10396 tANI_U8 i;
10397 hdd_context_t *pHddCtx;
10398
10399 ENTER();
10400
10401 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10402 if (NULL == pHddCtx) {
10403 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is Null"));
10404 goto allow_suspend;
10405 }
10406
10407 pScanInfo = &pHddCtx->scan_info;
10408
10409 hddLog(VOS_TRACE_LEVEL_INFO,
10410 "%s called with halHandle = %p, pContext = %p,"
10411 "scanID = %d, returned status = %d",
10412 __func__, halHandle, pContext, (int) scanId, (int) status);
10413
10414 pScanInfo->mScanPendingCounter = 0;
10415
10416 //Block on scan req completion variable. Can't wait forever though.
10417 waitRet = wait_for_completion_interruptible_timeout(
10418 &pScanInfo->scan_req_completion_event,
10419 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
10420 if (waitRet <= 0)
10421 {
10422 hddLog(VOS_TRACE_LEVEL_ERROR,
10423 "%s wait on scan_req_completion_event failed %ld",__func__, waitRet);
10424 VOS_ASSERT(pScanInfo->mScanPending);
10425 goto allow_suspend;
10426 }
10427
10428 if (pScanInfo->mScanPending != VOS_TRUE)
10429 {
10430 VOS_ASSERT(pScanInfo->mScanPending);
10431 goto allow_suspend;
10432 }
10433
10434 /* Check the scanId */
10435 if (pScanInfo->scanId != scanId)
10436 {
10437 hddLog(VOS_TRACE_LEVEL_INFO,
10438 "%s called with mismatched scanId pScanInfo->scanId = %d "
10439 "scanId = %d", __func__, (int) pScanInfo->scanId,
10440 (int) scanId);
10441 }
10442
10443 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
10444 pAdapter);
10445
10446 if (0 > ret)
10447 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
10448
10449
10450 /* If any client wait scan result through WEXT
10451 * send scan done event to client */
10452 if (pHddCtx->scan_info.waitScanResult)
10453 {
10454 /* The other scan request waiting for current scan finish
10455 * Send event to notify current scan finished */
10456 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
10457 {
10458 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
10459 }
10460 /* Send notify to WEXT client */
10461 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
10462 {
10463 struct net_device *dev = pAdapter->dev;
10464 union iwreq_data wrqu;
10465 int we_event;
10466 char *msg;
10467
10468 memset(&wrqu, '\0', sizeof(wrqu));
10469 we_event = SIOCGIWSCAN;
10470 msg = NULL;
10471 wireless_send_event(dev, we_event, &wrqu, msg);
10472 }
10473 }
10474 pHddCtx->scan_info.waitScanResult = FALSE;
10475
10476 /* Get the Scan Req */
10477 req = pAdapter->request;
10478
10479 if (!req)
10480 {
10481 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL");
10482 pScanInfo->mScanPending = VOS_FALSE;
10483 goto allow_suspend;
10484 }
10485
10486 pAdapter->request = NULL;
10487 /* Scan is no longer pending */
10488 pScanInfo->mScanPending = VOS_FALSE;
10489
10490 /* last_scan_timestamp is used to decide if new scan
10491 * is needed or not on station interface. If last station
10492 * scan time and new station scan time is less then
10493 * last_scan_timestamp ; driver will return cached scan.
10494 */
10495 if (req->no_cck == FALSE && status == eCSR_SCAN_SUCCESS) // no_cck will be set during p2p find
10496 {
10497 pScanInfo->last_scan_timestamp = vos_timer_get_system_time();
10498
10499 if ( req->n_channels )
10500 {
10501 for (i = 0; i < req->n_channels ; i++ )
10502 {
10503 pHddCtx->scan_info.last_scan_channelList[i] = req->channels[i]->hw_value;
10504 }
10505 /* store no of channel scanned */
10506 pHddCtx->scan_info.last_scan_numChannels= req->n_channels;
10507 }
10508
10509 }
10510
10511 /*
10512 * cfg80211_scan_done informing NL80211 about completion
10513 * of scanning
10514 */
10515 if (status == eCSR_SCAN_ABORT || status == eCSR_SCAN_FAILURE)
10516 {
10517 aborted = true;
10518 }
10519 cfg80211_scan_done(req, aborted);
10520 complete(&pScanInfo->abortscan_event_var);
10521
10522 if ((pHddCtx->cfg_ini->enableMacSpoofing == MAC_ADDR_SPOOFING_FW_HOST_ENABLE
10523 ) && (pHddCtx->spoofMacAddr.isEnabled
10524 || pHddCtx->spoofMacAddr.isReqDeferred)) {
10525 /* Generate new random mac addr for next scan */
10526 hddLog(VOS_TRACE_LEVEL_INFO, "scan completed - generate new spoof mac addr");
10527 hdd_processSpoofMacAddrRequest(pHddCtx);
10528 }
10529
10530allow_suspend:
10531 /* release the wake lock at the end of the scan*/
10532 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN);
10533
10534 /* Acquire wakelock to handle the case where APP's tries to suspend
10535 * immediatly after the driver gets connect request(i.e after scan)
10536 * from supplicant, this result in app's is suspending and not able
10537 * to process the connect request to AP */
10538 hdd_prevent_suspend_timeout(1000, WIFI_POWER_EVENT_WAKELOCK_SCAN);
10539
10540#ifdef FEATURE_WLAN_TDLS
10541 wlan_hdd_tdls_scan_done_callback(pAdapter);
10542#endif
10543
10544 EXIT();
10545 return 0;
10546}
10547
10548/*
10549 * FUNCTION: hdd_isConnectionInProgress
10550 * Go through each adapter and check if Connection is in progress
10551 *
10552 */
10553v_BOOL_t hdd_isConnectionInProgress( hdd_context_t *pHddCtx)
10554{
10555 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10556 hdd_station_ctx_t *pHddStaCtx = NULL;
10557 hdd_adapter_t *pAdapter = NULL;
10558 VOS_STATUS status = 0;
10559 v_U8_t staId = 0;
10560 v_U8_t *staMac = NULL;
10561
10562 if (TRUE == pHddCtx->btCoexModeSet)
10563 {
10564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10565 FL("BTCoex Mode operation in progress"));
10566 return VOS_TRUE;
10567 }
10568
10569 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10570
10571 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10572 {
10573 pAdapter = pAdapterNode->pAdapter;
10574
10575 if( pAdapter )
10576 {
10577 hddLog(VOS_TRACE_LEVEL_INFO,
10578 "%s: Adapter with device mode %s (%d) exists",
10579 __func__, hdd_device_modetoString(pAdapter->device_mode),
10580 pAdapter->device_mode);
10581 if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10582 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
10583 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)) &&
10584 (eConnectionState_Connecting ==
10585 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
10586 {
10587 hddLog(VOS_TRACE_LEVEL_ERROR,
10588 "%s: %p(%d) Connection is in progress", __func__,
10589 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
10590 return VOS_TRUE;
10591 }
10592 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
10593 smeNeighborMiddleOfRoaming(WLAN_HDD_GET_HAL_CTX(pAdapter)))
10594 {
10595 hddLog(VOS_TRACE_LEVEL_ERROR,
10596 "%s: %p(%d) Reassociation is in progress", __func__,
10597 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
10598 return VOS_TRUE;
10599 }
10600 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10601 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
10602 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
10603 {
10604 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10605 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
10606 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
10607 {
10608 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
10609 hddLog(VOS_TRACE_LEVEL_ERROR,
10610 "%s: client " MAC_ADDRESS_STR
10611 " is in the middle of WPS/EAPOL exchange.", __func__,
10612 MAC_ADDR_ARRAY(staMac));
10613 return VOS_TRUE;
10614 }
10615 }
10616 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
10617 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
10618 {
10619 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
10620 ptSapContext pSapCtx = NULL;
10621 pSapCtx = VOS_GET_SAP_CB(pVosContext);
10622 if(pSapCtx == NULL){
10623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10624 FL("psapCtx is NULL"));
10625 return VOS_FALSE;
10626 }
10627 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
10628 {
10629 if ((pSapCtx->aStaInfo[staId].isUsed) &&
10630 (WLANTL_STA_CONNECTED == pSapCtx->aStaInfo[staId].tlSTAState))
10631 {
10632 staMac = (v_U8_t *) &(pSapCtx->aStaInfo[staId].macAddrSTA.bytes[0]);
10633
10634 hddLog(VOS_TRACE_LEVEL_ERROR,
10635 "%s: client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the "
10636 "middle of WPS/EAPOL exchange.", __func__,
10637 MAC_ADDR_ARRAY(staMac));
10638 return VOS_TRUE;
10639 }
10640 }
10641 }
10642 }
10643 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10644 pAdapterNode = pNext;
10645 }
10646 return VOS_FALSE;
10647}
10648
10649/*
10650 * FUNCTION: __wlan_hdd_cfg80211_scan
10651 * this scan respond to scan trigger and update cfg80211 scan database
10652 * later, scan dump command can be used to recieve scan results
10653 */
10654int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
10655#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
10656 struct net_device *dev,
10657#endif
10658 struct cfg80211_scan_request *request)
10659{
10660 hdd_adapter_t *pAdapter = NULL;
10661 hdd_context_t *pHddCtx = NULL;
10662 hdd_wext_state_t *pwextBuf = NULL;
10663 hdd_config_t *cfg_param = NULL;
10664 tCsrScanRequest scanRequest;
10665 tANI_U8 *channelList = NULL, i;
10666 v_U32_t scanId = 0;
10667 int status;
10668 hdd_scaninfo_t *pScanInfo = NULL;
10669 v_U8_t* pP2pIe = NULL;
10670 int ret = 0;
10671 v_U8_t *pWpsIe=NULL;
10672 bool is_p2p_scan = false;
10673 v_S7_t rssi=0;
10674 hdd_station_ctx_t *pHddStaCtx=NULL;
10675
10676#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
10677 struct net_device *dev = NULL;
10678 if (NULL == request)
10679 {
10680 hddLog(VOS_TRACE_LEVEL_ERROR,
10681 "%s: scan req param null", __func__);
10682 return -EINVAL;
10683 }
10684 dev = request->wdev->netdev;
10685#endif
10686
10687 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
10688 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
10689 pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10690
10691 ENTER();
10692
10693 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
10694 __func__, hdd_device_modetoString(pAdapter->device_mode),
10695 pAdapter->device_mode);
10696
10697 status = wlan_hdd_validate_context(pHddCtx);
10698 if (0 != status)
10699 {
10700 return status;
10701 }
10702
10703 if (NULL == pwextBuf)
10704 {
10705 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: invalid WEXT state\n",
10706 __func__);
10707 return -EIO;
10708 }
10709 cfg_param = pHddCtx->cfg_ini;
10710 pScanInfo = &pHddCtx->scan_info;
10711
10712 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10713 if ( (pHddStaCtx != NULL) && (TRUE == hdd_connIsConnected(pHddStaCtx)))
10714 {
10715 wlan_hdd_get_roam_rssi(pAdapter, &rssi);
10716 hddLog(VOS_TRACE_LEVEL_INFO, FL("rssi: %d"), rssi);
10717 }
10718
10719#ifdef WLAN_BTAMP_FEATURE
10720 //Scan not supported when AMP traffic is on.
10721 if (VOS_TRUE == WLANBAP_AmpSessionOn())
10722 {
10723 hddLog(VOS_TRACE_LEVEL_ERROR,
10724 "%s: No scanning when AMP is on", __func__);
10725 return -EOPNOTSUPP;
10726 }
10727#endif
10728 //Scan on any other interface is not supported.
10729 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
10730 {
10731 hddLog(VOS_TRACE_LEVEL_ERROR,
10732 "%s: Not scanning on device_mode = %s (%d)",
10733 __func__, hdd_device_modetoString(pAdapter->device_mode),
10734 pAdapter->device_mode);
10735 return -EOPNOTSUPP;
10736 }
10737
10738 if (TRUE == pScanInfo->mScanPending)
10739 {
10740 if ( MAX_PENDING_LOG > pScanInfo->mScanPendingCounter++ )
10741 {
10742 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mScanPending is TRUE", __func__);
10743 }
10744 return -EBUSY;
10745 }
10746
10747 // Don't allow scan if PNO scan is going on.
10748 if (pHddCtx->isPnoEnable)
10749 {
10750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10751 FL("pno scan in progress"));
10752 return -EBUSY;
10753 }
10754
10755 //Don't Allow Scan and return busy if Remain On
10756 //Channel and action frame is pending
10757 //Otherwise Cancel Remain On Channel and allow Scan
10758 //If no action frame pending
10759 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
10760 {
10761 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Remain On Channel Pending", __func__);
10762 return -EBUSY;
10763 }
10764
10765 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
10766 {
10767 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
10768 "%s: Acquire lock fail", __func__);
10769 return -EAGAIN;
10770 }
10771 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
10772 {
10773 hddLog(VOS_TRACE_LEVEL_ERROR,
10774 "%s: MAX TM Level Scan not allowed", __func__);
10775 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
10776 return -EBUSY;
10777 }
10778 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
10779
10780 /* Check if scan is allowed at this point of time.
10781 */
10782 if (hdd_isConnectionInProgress(pHddCtx))
10783 {
10784 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
10785 return -EBUSY;
10786 }
10787
10788 vos_mem_zero( &scanRequest, sizeof(scanRequest));
10789
10790 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
10791 * Becasue of this, driver is assuming that this is not wildcard scan and so
10792 * is not aging out the scan results.
10793 */
10794 if (request->ssids && '\0' == request->ssids->ssid[0])
10795 {
10796 request->n_ssids = 0;
10797 }
10798
10799 if ((request->ssids) && (0 < request->n_ssids))
10800 {
10801 tCsrSSIDInfo *SsidInfo;
10802 int j;
10803 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
10804 /* Allocate num_ssid tCsrSSIDInfo structure */
10805 SsidInfo = scanRequest.SSIDs.SSIDList =
10806 ( tCsrSSIDInfo *)vos_mem_malloc(
10807 request->n_ssids*sizeof(tCsrSSIDInfo));
10808
10809 if(NULL == scanRequest.SSIDs.SSIDList)
10810 {
10811 hddLog(VOS_TRACE_LEVEL_ERROR,
10812 "%s: memory alloc failed SSIDInfo buffer", __func__);
10813 return -ENOMEM;
10814 }
10815
10816 /* copy all the ssid's and their length */
10817 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
10818 {
10819 /* get the ssid length */
10820 SsidInfo->SSID.length = request->ssids[j].ssid_len;
10821 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
10822 SsidInfo->SSID.length);
10823 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
10824 hddLog(VOS_TRACE_LEVEL_INFO, "SSID number %d: %s",
10825 j, SsidInfo->SSID.ssId);
10826 }
10827 /* set the scan type to active */
10828 scanRequest.scanType = eSIR_ACTIVE_SCAN;
10829 }
10830 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
10831 {
10832 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10833 TRACE_CODE_HDD_CFG80211_SCAN,
10834 pAdapter->sessionId, 0));
10835 /* set the scan type to active */
10836 scanRequest.scanType = eSIR_ACTIVE_SCAN;
10837 }
10838 else
10839 {
10840 /*Set the scan type to default type, in this case it is ACTIVE*/
10841 scanRequest.scanType = pScanInfo->scan_mode;
10842 }
10843 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
10844 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
10845
10846 /* set BSSType to default type */
10847 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
10848
10849 /*TODO: scan the requested channels only*/
10850
10851 /*Right now scanning all the channels */
10852 if (MAX_CHANNEL < request->n_channels)
10853 {
10854 hddLog(VOS_TRACE_LEVEL_WARN,
10855 "No of Scan Channels exceeded limit: %d", request->n_channels);
10856 request->n_channels = MAX_CHANNEL;
10857 }
10858
10859 hddLog(VOS_TRACE_LEVEL_INFO,
10860 "No of Scan Channels: %d", request->n_channels);
10861
10862
10863 if( request->n_channels )
10864 {
10865 char chList [(request->n_channels*5)+1];
10866 int len;
10867 channelList = vos_mem_malloc( request->n_channels );
10868 if( NULL == channelList )
10869 {
10870 hddLog(VOS_TRACE_LEVEL_ERROR,
10871 "%s: memory alloc failed channelList", __func__);
10872 status = -ENOMEM;
10873 goto free_mem;
10874 }
10875
10876 for( i = 0, len = 0; i < request->n_channels ; i++ )
10877 {
10878 channelList[i] = request->channels[i]->hw_value;
10879 len += snprintf(chList+len, 5, "%d ", channelList[i]);
10880 }
10881
10882 hddLog(VOS_TRACE_LEVEL_INFO,
10883 "Channel-List: %s ", chList);
10884 }
10885
10886 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
10887 scanRequest.ChannelInfo.ChannelList = channelList;
10888
10889 /* set requestType to full scan */
10890 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
10891
10892 /* if there is back to back scan happening in driver with in
10893 * nDeferScanTimeInterval interval driver should defer new scan request
10894 * and should provide last cached scan results instead of new channel list.
10895 * This rule is not applicable if scan is p2p scan.
10896 * This condition will work only in case when last request no of channels
10897 * and channels are exactly same as new request.
10898 * This should be done only in connected state
10899 * Scan shouldn't be defered for WPS scan case.
10900 */
10901
10902 pWpsIe = wlan_hdd_get_wps_ie_ptr((v_U8_t*)request->ie,request->ie_len);
10903 /* if wps ie is NULL , then only defer scan */
10904 if ( pWpsIe == NULL &&
10905 (VOS_STATUS_SUCCESS == hdd_is_any_session_connected(pHddCtx)))
10906 {
10907 if ( pScanInfo->last_scan_timestamp !=0 &&
10908 ((vos_timer_get_system_time() - pScanInfo->last_scan_timestamp ) < pHddCtx->cfg_ini->nDeferScanTimeInterval))
10909 {
10910 if ( request->no_cck == FALSE && scanRequest.ChannelInfo.numOfChannels != 1 &&
10911 (pScanInfo->last_scan_numChannels == scanRequest.ChannelInfo.numOfChannels) &&
10912 vos_mem_compare(pScanInfo->last_scan_channelList,
10913 channelList, pScanInfo->last_scan_numChannels))
10914 {
10915 hddLog(VOS_TRACE_LEVEL_WARN,
10916 " New and old station scan time differ is less then %u",
10917 pHddCtx->cfg_ini->nDeferScanTimeInterval);
10918
10919 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
10920 pAdapter);
10921
10922 hddLog(VOS_TRACE_LEVEL_WARN,
10923 "Return old cached scan as all channels and no of channels are same");
10924
10925 if (0 > ret)
10926 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
10927
10928 cfg80211_scan_done(request, eCSR_SCAN_SUCCESS);
10929
10930 status = eHAL_STATUS_SUCCESS;
10931 goto free_mem;
10932 }
10933 }
10934 }
10935
10936 /* Flush the scan results(only p2p beacons) for STA scan and P2P
10937 * search (Flush on both full scan and social scan but not on single
10938 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
10939 */
10940
10941 /* Supplicant does single channel scan after 8-way handshake
10942 * and in that case driver shoudnt flush scan results. If
10943 * driver flushes the scan results here and unfortunately if
10944 * the AP doesnt respond to our probe req then association
10945 * fails which is not desired
10946 */
10947 if ((request->n_ssids == 1)
10948 && (request->ssids != NULL)
10949 && vos_mem_compare(&request->ssids[0], "DIRECT-", 7))
10950 is_p2p_scan = true;
10951
10952 if( is_p2p_scan ||
10953 (request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN) )
10954 {
10955 hddLog(VOS_TRACE_LEVEL_DEBUG, "Flushing P2P Results");
10956 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
10957 pAdapter->sessionId );
10958 }
10959
10960 if( request->ie_len )
10961 {
10962 /* save this for future association (join requires this) */
10963 /*TODO: Array needs to be converted to dynamic allocation,
10964 * as multiple ie.s can be sent in cfg80211_scan_request structure
10965 * CR 597966
10966 */
10967 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
10968 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
10969 pScanInfo->scanAddIE.length = request->ie_len;
10970
10971 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10972 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
10973 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
10974 {
10975 if (request->ie_len <= SIR_MAC_MAX_ADD_IE_LENGTH)
10976 {
10977 pwextBuf->roamProfile.nAddIEScanLength = request->ie_len;
10978 memcpy( pwextBuf->roamProfile.addIEScan,
10979 request->ie, request->ie_len);
10980 }
10981 else
10982 {
10983 hddLog(VOS_TRACE_LEVEL_ERROR, "Scan Ie length is invalid:"
10984 "%zu", request->ie_len);
10985 }
10986
10987 }
10988 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
10989 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
10990
10991 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
10992 request->ie_len);
10993 if (pP2pIe != NULL)
10994 {
10995#ifdef WLAN_FEATURE_P2P_DEBUG
10996 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
10997 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
10998 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
10999 {
11000 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
11001 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
11002 "Go nego completed to Connection is started");
11003 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
11004 "for 8way Handshake");
11005 }
11006 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
11007 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
11008 {
11009 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
11010 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
11011 "Disconnected state to Connection is started");
11012 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
11013 "for 4way Handshake");
11014 }
11015#endif
11016
11017 /* no_cck will be set during p2p find to disable 11b rates */
11018 if(TRUE == request->no_cck)
11019 {
11020 hddLog(VOS_TRACE_LEVEL_INFO,
11021 "%s: This is a P2P Search", __func__);
11022 scanRequest.p2pSearch = 1;
11023
11024 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
11025 {
11026 /* set requestType to P2P Discovery */
11027 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
11028 }
11029
11030 /*
11031 Skip Dfs Channel in case of P2P Search
11032 if it is set in ini file
11033 */
11034 if(cfg_param->skipDfsChnlInP2pSearch)
11035 {
11036 scanRequest.skipDfsChnlInP2pSearch = 1;
11037 }
11038 else
11039 {
11040 scanRequest.skipDfsChnlInP2pSearch = 0;
11041 }
11042
11043 }
11044 }
11045 }
11046
11047 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
11048
11049#ifdef FEATURE_WLAN_TDLS
11050 /* if tdls disagree scan right now, return immediately.
11051 tdls will schedule the scan when scan is allowed. (return SUCCESS)
11052 or will reject the scan if any TDLS is in progress. (return -EBUSY)
11053 */
11054 status = wlan_hdd_tdls_scan_callback (pAdapter,
11055 wiphy,
11056#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11057 dev,
11058#endif
11059 request);
11060 if(status <= 0)
11061 {
11062 if(!status)
11063 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS in progress."
11064 "scan rejected %d", __func__, status);
11065 else
11066 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS teardown is ongoing %d",
11067 __func__, status);
11068 goto free_mem;
11069 }
11070#endif
11071
11072 /* acquire the wakelock to avoid the apps suspend during the scan. To
11073 * address the following issues.
11074 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
11075 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
11076 * for long time, this result in apps running at full power for long time.
11077 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
11078 * be stuck in full power because of resume BMPS
11079 */
11080 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN);
11081
11082 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
11083 "requestType %d, scanType %d, minChnTime %d, maxChnTime %d,"
11084 "p2pSearch %d, skipDfsChnlInP2pSearch %d",
11085 scanRequest.requestType, scanRequest.scanType,
11086 scanRequest.minChnTime, scanRequest.maxChnTime,
11087 scanRequest.p2pSearch, scanRequest.skipDfsChnlInP2pSearch);
11088
11089 if (pHddCtx->spoofMacAddr.isEnabled &&
11090 pHddCtx->cfg_ini->enableMacSpoofing == 1)
11091 {
11092 hddLog(VOS_TRACE_LEVEL_INFO,
11093 "%s: MAC Spoofing enabled for current scan", __func__);
11094 /* Updating SelfSta Mac Addr in TL which will be used to get staidx
11095 * to fill TxBds for probe request during current scan
11096 */
11097 status = WLANTL_updateSpoofMacAddr(pHddCtx->pvosContext,
11098 &pHddCtx->spoofMacAddr.randomMacAddr, &pAdapter->macAddressCurrent);
11099
11100 if(status != VOS_STATUS_SUCCESS)
11101 {
11102 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN);
11103 status = -EFAULT;
11104#ifdef FEATURE_WLAN_TDLS
11105 wlan_hdd_tdls_scan_done_callback(pAdapter);
11106#endif
11107 goto free_mem;
11108 }
11109 }
11110 wlan_hdd_get_frame_logs(pAdapter, WLAN_HDD_GET_FRAME_LOG_CMD_CLEAR);
11111 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
11112 pAdapter->sessionId, &scanRequest, &scanId,
11113 &hdd_cfg80211_scan_done_callback, dev );
11114
11115 if (eHAL_STATUS_SUCCESS != status)
11116 {
11117 hddLog(VOS_TRACE_LEVEL_ERROR,
11118 "%s: sme_ScanRequest returned error %d", __func__, status);
11119 complete(&pScanInfo->scan_req_completion_event);
11120 if(eHAL_STATUS_RESOURCES == status)
11121 {
11122 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HO is in progress."
11123 "So defer the scan by informing busy",__func__);
11124 status = -EBUSY;
11125 } else {
11126 status = -EIO;
11127 }
11128 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_SCAN);
11129
11130#ifdef FEATURE_WLAN_TDLS
11131 wlan_hdd_tdls_scan_done_callback(pAdapter);
11132#endif
11133 goto free_mem;
11134 }
11135
11136 pScanInfo->mScanPending = TRUE;
11137 pScanInfo->sessionId = pAdapter->sessionId;
11138 pAdapter->request = request;
11139 pScanInfo->scanId = scanId;
11140
11141 complete(&pScanInfo->scan_req_completion_event);
11142
11143free_mem:
11144 if( scanRequest.SSIDs.SSIDList )
11145 {
11146 vos_mem_free(scanRequest.SSIDs.SSIDList);
11147 }
11148
11149 if( channelList )
11150 vos_mem_free( channelList );
11151
11152 EXIT();
11153 return status;
11154}
11155
11156int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
11157#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11158 struct net_device *dev,
11159#endif
11160 struct cfg80211_scan_request *request)
11161{
11162 int ret;
11163
11164 vos_ssr_protect(__func__);
11165 ret = __wlan_hdd_cfg80211_scan(wiphy,
11166#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11167 dev,
11168#endif
11169 request);
11170 vos_ssr_unprotect(__func__);
11171
11172 return ret;
11173}
11174
11175void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
11176{
11177 v_U8_t iniDot11Mode =
11178 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
11179 eHddDot11Mode hddDot11Mode = iniDot11Mode;
11180
11181 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"),
11182 iniDot11Mode);
11183 switch ( iniDot11Mode )
11184 {
11185 case eHDD_DOT11_MODE_AUTO:
11186 case eHDD_DOT11_MODE_11ac:
11187 case eHDD_DOT11_MODE_11ac_ONLY:
11188#ifdef WLAN_FEATURE_11AC
11189 if ( sme_IsFeatureSupportedByDriver(DOT11AC) &&
11190 sme_IsFeatureSupportedByFW(DOT11AC) )
11191 hddDot11Mode = eHDD_DOT11_MODE_11ac;
11192 else
11193 hddDot11Mode = eHDD_DOT11_MODE_11n;
11194#else
11195 hddDot11Mode = eHDD_DOT11_MODE_11n;
11196#endif
11197 break;
11198 case eHDD_DOT11_MODE_11n:
11199 case eHDD_DOT11_MODE_11n_ONLY:
11200 hddDot11Mode = eHDD_DOT11_MODE_11n;
11201 break;
11202 default:
11203 hddDot11Mode = iniDot11Mode;
11204 break;
11205 }
11206#ifdef WLAN_FEATURE_AP_HT40_24G
11207 if (operationChannel > SIR_11B_CHANNEL_END)
11208#endif
11209 {
11210 /* This call decides required channel bonding mode */
11211 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
11212 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
11213 operationChannel);
11214 }
11215}
11216
11217/*
11218 * FUNCTION: wlan_hdd_cfg80211_connect_start
11219 * This function is used to start the association process
11220 */
11221int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
11222 const u8 *ssid, size_t ssid_len, const u8 *bssid,
11223 const u8 *bssid_hint, u8 operatingChannel)
11224{
11225 int status = 0;
11226 hdd_wext_state_t *pWextState;
11227 hdd_context_t *pHddCtx;
11228 v_U32_t roamId;
11229 tCsrRoamProfile *pRoamProfile;
11230 eCsrAuthType RSNAuthType;
11231 const u8 *pValidBssid = NULL;
11232
11233 ENTER();
11234
11235 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11236 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11237
11238 status = wlan_hdd_validate_context(pHddCtx);
11239 if (status)
11240 {
11241 return status;
11242 }
11243
11244 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
11245 {
11246 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
11247 return -EINVAL;
11248 }
11249
11250 pRoamProfile = &pWextState->roamProfile;
11251
11252 if (pRoamProfile)
11253 {
11254 hdd_station_ctx_t *pHddStaCtx;
11255 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11256
11257 wlan_hdd_get_frame_logs(pAdapter, WLAN_HDD_GET_FRAME_LOG_CMD_CLEAR);
11258
11259 if (HDD_WMM_USER_MODE_NO_QOS ==
11260 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
11261 {
11262 /*QoS not enabled in cfg file*/
11263 pRoamProfile->uapsd_mask = 0;
11264 }
11265 else
11266 {
11267 /*QoS enabled, update uapsd mask from cfg file*/
11268 pRoamProfile->uapsd_mask =
11269 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
11270 }
11271
11272 pRoamProfile->SSIDs.numOfSSIDs = 1;
11273 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
11274 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11275 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
11276 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
11277 ssid, ssid_len);
11278
11279 if (bssid)
11280 {
11281 pValidBssid = bssid;
11282 }
11283 else if (bssid_hint)
11284 {
11285 pValidBssid = bssid_hint;
11286 }
11287 if (pValidBssid)
11288 {
11289 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
11290 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), pValidBssid,
11291 WNI_CFG_BSSID_LEN);
11292 /* Save BSSID in seperate variable as well, as RoamProfile
11293 BSSID is getting zeroed out in the association process. And in
11294 case of join failure we should send valid BSSID to supplicant
11295 */
11296 vos_mem_copy((void *)(pWextState->req_bssId), pValidBssid,
11297 WNI_CFG_BSSID_LEN);
11298 }
11299 else
11300 {
11301 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
11302 }
11303
11304 hddLog(LOG1, FL("Connect to SSID: %s opertating Channel: %u"),
11305 pRoamProfile->SSIDs.SSIDList->SSID.ssId, operatingChannel);
11306 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11307 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
11308 {
11309 /*set gen ie*/
11310 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
11311 /*set auth*/
11312 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11313 }
11314#ifdef FEATURE_WLAN_WAPI
11315 if (pAdapter->wapi_info.nWapiMode)
11316 {
11317 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
11318 switch (pAdapter->wapi_info.wapiAuthMode)
11319 {
11320 case WAPI_AUTH_MODE_PSK:
11321 {
11322 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
11323 pAdapter->wapi_info.wapiAuthMode);
11324 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11325 break;
11326 }
11327 case WAPI_AUTH_MODE_CERT:
11328 {
11329 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
11330 pAdapter->wapi_info.wapiAuthMode);
11331 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11332 break;
11333 }
11334 } // End of switch
11335 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
11336 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
11337 {
11338 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
11339 pRoamProfile->AuthType.numEntries = 1;
11340 pRoamProfile->EncryptionType.numEntries = 1;
11341 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11342 pRoamProfile->mcEncryptionType.numEntries = 1;
11343 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11344 }
11345 }
11346#endif /* FEATURE_WLAN_WAPI */
11347#ifdef WLAN_FEATURE_GTK_OFFLOAD
11348 /* Initializing gtkOffloadReqParams */
11349 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
11350 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
11351 {
11352 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11353 sizeof (tSirGtkOffloadParams));
11354 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
11355 }
11356#endif
11357 pRoamProfile->csrPersona = pAdapter->device_mode;
11358
11359 if( operatingChannel )
11360 {
11361 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
11362 pRoamProfile->ChannelInfo.numOfChannels = 1;
11363 }
11364 else
11365 {
11366 pRoamProfile->ChannelInfo.ChannelList = NULL;
11367 pRoamProfile->ChannelInfo.numOfChannels = 0;
11368 }
11369 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
11370 {
11371 hdd_select_cbmode(pAdapter,operatingChannel);
11372 }
11373
11374 /*
11375 * Change conn_state to connecting before sme_RoamConnect(),
11376 * because sme_RoamConnect() has a direct path to call
11377 * hdd_smeRoamCallback(), which will change the conn_state
11378 * If direct path, conn_state will be accordingly changed
11379 * to NotConnected or Associated by either
11380 * hdd_AssociationCompletionHandler() or hdd_DisConnectHandler()
11381 * in sme_RoamCallback()
11382 * if sme_RomConnect is to be queued,
11383 * Connecting state will remain until it is completed.
11384 * If connection state is not changed,
11385 * connection state will remain in eConnectionState_NotConnected state.
11386 * In hdd_AssociationCompletionHandler, "hddDisconInProgress" is set to true
11387 * if conn state is eConnectionState_NotConnected.
11388 * If "hddDisconInProgress" is set to true then cfg80211 layer is not
11389 * informed of connect result indication which is an issue.
11390 */
11391
11392 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
11393 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
11394 {
11395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
11396 FL("Set HDD connState to eConnectionState_Connecting"));
11397 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
11398 eConnectionState_Connecting);
11399 }
11400 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
11401 pAdapter->sessionId, pRoamProfile, &roamId);
11402
11403 if ((eHAL_STATUS_SUCCESS != status) &&
11404 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
11405 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
11406
11407 {
11408 hddLog(VOS_TRACE_LEVEL_ERROR,
11409 FL("sme_RoamConnect (session %d) failed with status %d. -> NotConnected"),
11410 pAdapter->sessionId, status);
11411 /* change back to NotAssociated */
11412 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
11413 eConnectionState_NotConnected);
11414 }
11415
11416 pRoamProfile->ChannelInfo.ChannelList = NULL;
11417 pRoamProfile->ChannelInfo.numOfChannels = 0;
11418
11419 }
11420 else
11421 {
11422 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
11423 return -EINVAL;
11424 }
11425 EXIT();
11426 return status;
11427}
11428
11429/*
11430 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
11431 * This function is used to set the authentication type (OPEN/SHARED).
11432 *
11433 */
11434static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11435 enum nl80211_auth_type auth_type)
11436{
11437 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11438 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11439
11440 ENTER();
11441
11442 /*set authentication type*/
11443 switch (auth_type)
11444 {
11445 case NL80211_AUTHTYPE_AUTOMATIC:
11446 hddLog(VOS_TRACE_LEVEL_INFO,
11447 "%s: set authentication type to AUTOSWITCH", __func__);
11448 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11449 break;
11450
11451 case NL80211_AUTHTYPE_OPEN_SYSTEM:
11452#ifdef WLAN_FEATURE_VOWIFI_11R
11453 case NL80211_AUTHTYPE_FT:
11454#endif /* WLAN_FEATURE_VOWIFI_11R */
11455 hddLog(VOS_TRACE_LEVEL_INFO,
11456 "%s: set authentication type to OPEN", __func__);
11457 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11458 break;
11459
11460 case NL80211_AUTHTYPE_SHARED_KEY:
11461 hddLog(VOS_TRACE_LEVEL_INFO,
11462 "%s: set authentication type to SHARED", __func__);
11463 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11464 break;
11465#ifdef FEATURE_WLAN_ESE
11466 case NL80211_AUTHTYPE_NETWORK_EAP:
11467 hddLog(VOS_TRACE_LEVEL_INFO,
11468 "%s: set authentication type to CCKM WPA", __func__);
11469 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
11470 break;
11471#endif
11472
11473
11474 default:
11475 hddLog(VOS_TRACE_LEVEL_ERROR,
11476 "%s: Unsupported authentication type %d", __func__,
11477 auth_type);
11478 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11479 return -EINVAL;
11480 }
11481
11482 pWextState->roamProfile.AuthType.authType[0] =
11483 pHddStaCtx->conn_info.authType;
11484 return 0;
11485}
11486
11487/*
11488 * FUNCTION: wlan_hdd_set_akm_suite
11489 * This function is used to set the key mgmt type(PSK/8021x).
11490 *
11491 */
11492static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
11493 u32 key_mgmt
11494 )
11495{
11496 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11497 ENTER();
11498 /* Should be in ieee802_11_defs.h */
11499#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11500#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11501 /*set key mgmt type*/
11502 switch(key_mgmt)
11503 {
11504 case WLAN_AKM_SUITE_PSK:
11505 case WLAN_AKM_SUITE_PSK_SHA256:
11506#ifdef WLAN_FEATURE_VOWIFI_11R
11507 case WLAN_AKM_SUITE_FT_PSK:
11508#endif
11509 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
11510 __func__);
11511 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11512 break;
11513
11514 case WLAN_AKM_SUITE_8021X:
11515 case WLAN_AKM_SUITE_8021X_SHA256:
11516#ifdef WLAN_FEATURE_VOWIFI_11R
11517 case WLAN_AKM_SUITE_FT_8021X:
11518#endif
11519 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
11520 __func__);
11521 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11522 break;
11523#ifdef FEATURE_WLAN_ESE
11524#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11525#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11526 case WLAN_AKM_SUITE_CCKM:
11527 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
11528 __func__);
11529 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11530 break;
11531#endif
11532#ifndef WLAN_AKM_SUITE_OSEN
11533#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11534 case WLAN_AKM_SUITE_OSEN:
11535 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to OSEN",
11536 __func__);
11537 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11538 break;
11539#endif
11540
11541 default:
11542 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
11543 __func__, key_mgmt);
11544 return -EINVAL;
11545
11546 }
11547 return 0;
11548}
11549
11550/*
11551 * FUNCTION: wlan_hdd_cfg80211_set_cipher
11552 * This function is used to set the encryption type
11553 * (NONE/WEP40/WEP104/TKIP/CCMP).
11554 */
11555static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
11556 u32 cipher,
11557 bool ucast
11558 )
11559{
11560 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11561 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11562 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11563
11564 ENTER();
11565
11566 if (!cipher)
11567 {
11568 hddLog(VOS_TRACE_LEVEL_INFO, "%s: received cipher %d - considering none",
11569 __func__, cipher);
11570 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11571 }
11572 else
11573 {
11574
11575 /*set encryption method*/
11576 switch (cipher)
11577 {
11578 case IW_AUTH_CIPHER_NONE:
11579 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11580 break;
11581
11582 case WLAN_CIPHER_SUITE_WEP40:
11583 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11584 break;
11585
11586 case WLAN_CIPHER_SUITE_WEP104:
11587 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11588 break;
11589
11590 case WLAN_CIPHER_SUITE_TKIP:
11591 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11592 break;
11593
11594 case WLAN_CIPHER_SUITE_CCMP:
11595 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11596 break;
11597#ifdef FEATURE_WLAN_WAPI
11598 case WLAN_CIPHER_SUITE_SMS4:
11599 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11600 break;
11601#endif
11602
11603#ifdef FEATURE_WLAN_ESE
11604 case WLAN_CIPHER_SUITE_KRK:
11605 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11606 break;
11607#endif
11608 default:
11609 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
11610 __func__, cipher);
11611 return -EOPNOTSUPP;
11612 }
11613 }
11614
11615 if (ucast)
11616 {
11617 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
11618 __func__, encryptionType);
11619 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11620 pWextState->roamProfile.EncryptionType.numEntries = 1;
11621 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11622 encryptionType;
11623 }
11624 else
11625 {
11626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
11627 __func__, encryptionType);
11628 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11629 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11630 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
11631 }
11632
11633 return 0;
11634}
11635
11636
11637/*
11638 * FUNCTION: wlan_hdd_cfg80211_set_ie
11639 * This function is used to parse WPA/RSN IE's.
11640 */
11641int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
11642#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
11643 const u8 *ie,
11644#else
11645 u8 *ie,
11646#endif
11647 size_t ie_len
11648 )
11649{
11650 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11651#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
11652 const u8 *genie = ie;
11653#else
11654 u8 *genie = ie;
11655#endif
11656 v_U16_t remLen = ie_len;
11657#ifdef FEATURE_WLAN_WAPI
11658 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
11659 u16 *tmp;
11660 v_U16_t akmsuiteCount;
11661 int *akmlist;
11662#endif
11663 ENTER();
11664
11665 /* clear previous assocAddIE */
11666 pWextState->assocAddIE.length = 0;
11667 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
11668 pWextState->roamProfile.bOSENAssociation = VOS_FALSE;
11669
11670 while (remLen >= 2)
11671 {
11672 v_U16_t eLen = 0;
11673 v_U8_t elementId;
11674 elementId = *genie++;
11675 eLen = *genie++;
11676 remLen -= 2;
11677
11678 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]",
11679 __func__, elementId, eLen);
11680
11681 switch ( elementId )
11682 {
11683 case DOT11F_EID_WPA:
11684 if (4 > eLen) /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
11685 {
11686 hddLog(VOS_TRACE_LEVEL_ERROR,
11687 "%s: Invalid WPA IE", __func__);
11688 return -EINVAL;
11689 }
11690 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
11691 {
11692 v_U16_t curAddIELen = pWextState->assocAddIE.length;
11693 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
11694 __func__, eLen + 2);
11695
11696 if( SIR_MAC_MAX_ADD_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
11697 {
11698 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
11699 "Need bigger buffer space");
11700 VOS_ASSERT(0);
11701 return -ENOMEM;
11702 }
11703 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
11704 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
11705 pWextState->assocAddIE.length += eLen + 2;
11706
11707 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
11708 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
11709 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
11710 }
11711 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
11712 {
11713 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
11714 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
11715 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
11716 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
11717 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
11718 }
11719 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
11720 P2P_OUI_TYPE_SIZE)))
11721 {
11722 v_U16_t curAddIELen = pWextState->assocAddIE.length;
11723 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
11724 __func__, eLen + 2);
11725
11726 if( SIR_MAC_MAX_ADD_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
11727 {
11728 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
11729 "Need bigger buffer space");
11730 VOS_ASSERT(0);
11731 return -ENOMEM;
11732 }
11733 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
11734 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
11735 pWextState->assocAddIE.length += eLen + 2;
11736
11737 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
11738 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
11739 }
11740#ifdef WLAN_FEATURE_WFD
11741 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
11742 WFD_OUI_TYPE_SIZE))
11743 /*Consider WFD IE, only for P2P Client */
11744 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
11745 {
11746 v_U16_t curAddIELen = pWextState->assocAddIE.length;
11747 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
11748 __func__, eLen + 2);
11749
11750 if( SIR_MAC_MAX_ADD_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
11751 {
11752 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
11753 "Need bigger buffer space");
11754 VOS_ASSERT(0);
11755 return -ENOMEM;
11756 }
11757 // WFD IE is saved to Additional IE ; it should be accumulated to handle
11758 // WPS IE + P2P IE + WFD IE
11759 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
11760 pWextState->assocAddIE.length += eLen + 2;
11761
11762 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
11763 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
11764 }
11765#endif
11766 /* Appending HS 2.0 Indication Element in Assiciation Request */
11767 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
11768 HS20_OUI_TYPE_SIZE)) )
11769 {
11770 v_U16_t curAddIELen = pWextState->assocAddIE.length;
11771 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
11772 __func__, eLen + 2);
11773
11774 if( SIR_MAC_MAX_ADD_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
11775 {
11776 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
11777 "Need bigger buffer space");
11778 VOS_ASSERT(0);
11779 return -ENOMEM;
11780 }
11781 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
11782 pWextState->assocAddIE.length += eLen + 2;
11783
11784 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
11785 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
11786 }
11787 /* Appending OSEN Information Element in Assiciation Request */
11788 else if ( (0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11789 OSEN_OUI_TYPE_SIZE)) )
11790 {
11791 v_U16_t curAddIELen = pWextState->assocAddIE.length;
11792 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OSEN IE(len %d)",
11793 __func__, eLen + 2);
11794
11795 if( SIR_MAC_MAX_ADD_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
11796 {
11797 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
11798 "Need bigger buffer space");
11799 VOS_ASSERT(0);
11800 return -ENOMEM;
11801 }
11802 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
11803 pWextState->assocAddIE.length += eLen + 2;
11804
11805 pWextState->roamProfile.bOSENAssociation = VOS_TRUE;
11806 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
11807 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
11808 }
11809
11810 /* Update only for WPA IE */
11811 if (!memcmp(genie, WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) &&
11812 (WLAN_HDD_IBSS == pAdapter->device_mode)) {
11813
11814 /* populating as ADDIE in beacon frames */
11815 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
11816 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, (u8 *)genie - 2, eLen + 2,
11817 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
11818 {
11819 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
11820 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
11821 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
11822 {
11823 hddLog(LOGE,
11824 "Coldn't pass "
11825 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
11826 }
11827 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
11828 else
11829 hddLog(LOGE,
11830 "Could not pass on "
11831 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
11832
11833 /* IBSS mode doesn't contain params->proberesp_ies still
11834 beaconIE's need to be populated in probe response frames */
11835 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
11836 {
11837 u16 rem_probe_resp_ie_len = eLen + 2;
11838 u8 probe_rsp_ie_len[3] = {0};
11839 u8 counter = 0;
11840
11841 /* Check Probe Resp Length if it is greater then 255 then
11842 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
11843 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
11844 not able Store More then 255 bytes into One Variable */
11845
11846 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
11847 {
11848 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
11849 {
11850 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
11851 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
11852 }
11853 else
11854 {
11855 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
11856 rem_probe_resp_ie_len = 0;
11857 }
11858 }
11859
11860 rem_probe_resp_ie_len = 0;
11861
11862 if (probe_rsp_ie_len[0] > 0)
11863 {
11864 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
11865 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
11866 (tANI_U8*)(genie - 2),
11867 probe_rsp_ie_len[0], NULL,
11868 eANI_BOOLEAN_FALSE)
11869 == eHAL_STATUS_FAILURE)
11870 {
11871 hddLog(LOGE,
11872 "Could not pass"
11873 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
11874 }
11875 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
11876 }
11877
11878 if (probe_rsp_ie_len[1] > 0)
11879 {
11880 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
11881 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
11882 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
11883 probe_rsp_ie_len[1], NULL,
11884 eANI_BOOLEAN_FALSE)
11885 == eHAL_STATUS_FAILURE)
11886 {
11887 hddLog(LOGE,
11888 "Could not pass"
11889 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
11890 }
11891 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
11892 }
11893
11894 if (probe_rsp_ie_len[2] > 0)
11895 {
11896 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
11897 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
11898 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
11899 probe_rsp_ie_len[2], NULL,
11900 eANI_BOOLEAN_FALSE)
11901 == eHAL_STATUS_FAILURE)
11902 {
11903 hddLog(LOGE,
11904 "Could not pass"
11905 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
11906 }
11907 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
11908 }
11909
11910 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
11911 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
11912 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
11913 {
11914 hddLog(LOGE,
11915 "Could not pass"
11916 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
11917 }
11918 }
11919 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
11920 break;
11921 case DOT11F_EID_RSN:
11922 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
11923 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
11924 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
11925 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
11926 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
11927 break;
11928
11929 /* Appending Extended Capabilities with Interworking bit set
11930 * in Assoc Req.
11931 *
11932 * In assoc req this EXT Cap will only be taken into account if
11933 * interworkingService bit is set to 1. Currently
11934 * driver is only interested in interworkingService capability
11935 * from supplicant. If in future any other EXT Cap info is
11936 * required from supplicat, it needs to be handled while
11937 * sending Assoc Req in LIM.
11938 */
11939 case DOT11F_EID_EXTCAP:
11940 {
11941 v_U16_t curAddIELen = pWextState->assocAddIE.length;
11942 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
11943 __func__, eLen + 2);
11944
11945 if( SIR_MAC_MAX_ADD_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
11946 {
11947 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
11948 "Need bigger buffer space");
11949 VOS_ASSERT(0);
11950 return -ENOMEM;
11951 }
11952 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
11953 pWextState->assocAddIE.length += eLen + 2;
11954
11955 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
11956 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
11957 break;
11958 }
11959#ifdef FEATURE_WLAN_WAPI
11960 case WLAN_EID_WAPI:
11961 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
11962 hddLog(VOS_TRACE_LEVEL_INFO, "WAPI MODE IS %u",
11963 pAdapter->wapi_info.nWapiMode);
11964 tmp = (u16 *)ie;
11965 tmp = tmp + 2; // Skip element Id and Len, Version
11966 akmsuiteCount = WPA_GET_LE16(tmp);
11967 tmp = tmp + 1;
11968 akmlist = (int *)(tmp);
11969 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
11970 {
11971 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
11972 }
11973 else
11974 {
11975 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count");
11976 VOS_ASSERT(0);
11977 return -EINVAL;
11978 }
11979
11980 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
11981 {
11982 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
11983 __func__);
11984 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
11985 }
11986 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
11987 {
11988 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
11989 __func__);
11990 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
11991 }
11992 break;
11993#endif
11994 default:
11995 hddLog (VOS_TRACE_LEVEL_ERROR,
11996 "%s Set UNKNOWN IE %X", __func__, elementId);
11997 /* when Unknown IE is received we should break and continue
11998 * to the next IE in the buffer instead we were returning
11999 * so changing this to break */
12000 break;
12001 }
12002 genie += eLen;
12003 remLen -= eLen;
12004 }
12005 EXIT();
12006 return 0;
12007}
12008
12009/*
12010 * FUNCTION: hdd_isWPAIEPresent
12011 * Parse the received IE to find the WPA IE
12012 *
12013 */
12014static bool hdd_isWPAIEPresent(
12015#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
12016 const u8 *ie,
12017#else
12018 u8 *ie,
12019#endif
12020 u8 ie_len)
12021{
12022 v_U8_t eLen = 0;
12023 v_U16_t remLen = ie_len;
12024 v_U8_t elementId = 0;
12025
12026 while (remLen >= 2)
12027 {
12028 elementId = *ie++;
12029 eLen = *ie++;
12030 remLen -= 2;
12031 if (eLen > remLen)
12032 {
12033 hddLog(VOS_TRACE_LEVEL_ERROR,
12034 "%s: IE length is wrong %d", __func__, eLen);
12035 return FALSE;
12036 }
12037 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
12038 {
12039 /* OUI - 0x00 0X50 0XF2
12040 WPA Information Element - 0x01
12041 WPA version - 0x01*/
12042 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12043 return TRUE;
12044 }
12045 ie += eLen;
12046 remLen -= eLen;
12047 }
12048 return FALSE;
12049}
12050
12051/*
12052 * FUNCTION: wlan_hdd_cfg80211_set_privacy
12053 * This function is used to initialize the security
12054 * parameters during connect operation.
12055 */
12056int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12057 struct cfg80211_connect_params *req
12058 )
12059{
12060 int status = 0;
12061 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12062 ENTER();
12063
12064 /*set wpa version*/
12065 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12066
12067 if (req->crypto.wpa_versions)
12068 {
12069 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
12070 {
12071 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12072 }
12073 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
12074 {
12075 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12076 }
12077 }
12078
12079 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
12080 pWextState->wpaVersion);
12081
12082 /*set authentication type*/
12083 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12084
12085 if (0 > status)
12086 {
12087 hddLog(VOS_TRACE_LEVEL_ERROR,
12088 "%s: failed to set authentication type ", __func__);
12089 return status;
12090 }
12091
12092 /*set key mgmt type*/
12093 if (req->crypto.n_akm_suites)
12094 {
12095 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12096 if (0 > status)
12097 {
12098 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
12099 __func__);
12100 return status;
12101 }
12102 }
12103
12104 /*set pairwise cipher type*/
12105 if (req->crypto.n_ciphers_pairwise)
12106 {
12107 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12108 req->crypto.ciphers_pairwise[0], true);
12109 if (0 > status)
12110 {
12111 hddLog(VOS_TRACE_LEVEL_ERROR,
12112 "%s: failed to set unicast cipher type", __func__);
12113 return status;
12114 }
12115 }
12116 else
12117 {
12118 /*Reset previous cipher suite to none*/
12119 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12120 if (0 > status)
12121 {
12122 hddLog(VOS_TRACE_LEVEL_ERROR,
12123 "%s: failed to set unicast cipher type", __func__);
12124 return status;
12125 }
12126 }
12127
12128 /*set group cipher type*/
12129 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12130 false);
12131
12132 if (0 > status)
12133 {
12134 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
12135 __func__);
12136 return status;
12137 }
12138
12139#ifdef WLAN_FEATURE_11W
12140 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12141#endif
12142
12143 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
12144 if (req->ie_len)
12145 {
12146 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12147 if ( 0 > status)
12148 {
12149 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
12150 __func__);
12151 return status;
12152 }
12153 }
12154
12155 /*incase of WEP set default key information*/
12156 if (req->key && req->key_len)
12157 {
12158 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12159 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
12160 )
12161 {
12162 if ( IW_AUTH_KEY_MGMT_802_1X
12163 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
12164 {
12165 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
12166 __func__);
12167 return -EOPNOTSUPP;
12168 }
12169 else
12170 {
12171 u8 key_len = req->key_len;
12172 u8 key_idx = req->key_idx;
12173
12174 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
12175 && (CSR_MAX_NUM_KEY > key_idx)
12176 )
12177 {
12178 hddLog(VOS_TRACE_LEVEL_INFO,
12179 "%s: setting default wep key, key_idx = %hu key_len %hu",
12180 __func__, key_idx, key_len);
12181 vos_mem_copy(
12182 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
12183 req->key, key_len);
12184 pWextState->roamProfile.Keys.KeyLength[key_idx] =
12185 (u8)key_len;
12186 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
12187 }
12188 }
12189 }
12190 }
12191
12192 return status;
12193}
12194
12195/*
12196 * FUNCTION: wlan_hdd_try_disconnect
12197 * This function is used to disconnect from previous
12198 * connection
12199 */
12200static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter )
12201{
12202 long ret = 0;
12203 hdd_station_ctx_t *pHddStaCtx;
12204 eMib_dot11DesiredBssType connectedBssType;
12205
12206 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12207
12208 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
12209
12210 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
12211 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12212 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
12213 {
12214 /* Issue disconnect to CSR */
12215 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12216 if( eHAL_STATUS_SUCCESS ==
12217 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
12218 pAdapter->sessionId,
12219 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
12220 {
12221 ret = wait_for_completion_interruptible_timeout(
12222 &pAdapter->disconnect_comp_var,
12223 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
12224 if (0 >= ret)
12225 {
12226 hddLog(LOGE, FL("Failed to receive disconnect event"));
12227 return -EALREADY;
12228 }
12229 }
12230 }
12231 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
12232 {
12233 ret = wait_for_completion_interruptible_timeout(
12234 &pAdapter->disconnect_comp_var,
12235 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
12236 if (0 >= ret)
12237 {
12238 hddLog(LOGE, FL("Failed to receive disconnect event"));
12239 return -EALREADY;
12240 }
12241 }
12242
12243 return 0;
12244}
12245
12246/*
12247 * FUNCTION: __wlan_hdd_cfg80211_connect
12248 * This function is used to start the association process
12249 */
12250static int __wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
12251 struct net_device *ndev,
12252 struct cfg80211_connect_params *req
12253 )
12254{
12255 int status;
12256 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
12257 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
12258 hdd_context_t *pHddCtx = NULL;
12259
12260 ENTER();
12261
12262 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12263 TRACE_CODE_HDD_CFG80211_CONNECT,
12264 pAdapter->sessionId, pAdapter->device_mode));
12265 hddLog(VOS_TRACE_LEVEL_INFO,
12266 "%s: device_mode = %s (%d)", __func__,
12267 hdd_device_modetoString(pAdapter->device_mode),
12268 pAdapter->device_mode);
12269
12270 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12271 if (!pHddCtx)
12272 {
12273 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12274 "%s: HDD context is null", __func__);
12275 return -EINVAL;
12276 }
12277
12278 status = wlan_hdd_validate_context(pHddCtx);
12279 if (0 != status)
12280 {
12281 return status;
12282 }
12283
Gururaj Patil6b8abb32019-09-23 13:48:29 +000012284 if (vos_max_concurrent_connections_reached()) {
12285 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
12286 return -ECONNREFUSED;
12287 }
chrmhoffmannbb97ca42017-05-13 21:27:44 +020012288
12289#ifdef WLAN_BTAMP_FEATURE
12290 //Infra connect not supported when AMP traffic is on.
12291 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
12292 {
12293 hddLog(VOS_TRACE_LEVEL_ERROR,
12294 "%s: No connection when AMP is on", __func__);
12295 return -ECONNREFUSED;
12296 }
12297#endif
12298
12299 //If Device Mode is Station Concurrent Sessions Exit BMps
12300 //P2P Mode will be taken care in Open/close adapter
12301 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
12302 (vos_concurrent_open_sessions_running())) {
12303 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx,
12304 WLAN_HDD_INFRA_STATION);
12305 }
12306
12307 /*Try disconnecting if already in connected state*/
12308 status = wlan_hdd_try_disconnect(pAdapter);
12309 if ( 0 > status)
12310 {
12311 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
12312 " connection"));
12313 return -EALREADY;
12314 }
12315
12316 /*initialise security parameters*/
12317 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12318
12319 if ( 0 > status)
12320 {
12321 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
12322 __func__);
12323 return status;
12324 }
12325
12326 if (pHddCtx->spoofMacAddr.isEnabled)
12327 {
12328 hddLog(VOS_TRACE_LEVEL_INFO,
12329 "%s: MAC Spoofing enabled ", __func__);
12330 /* Updating SelfSta Mac Addr in TL which will be used to get staidx
12331 * to fill TxBds for probe request during SSID scan which may happen
12332 * as part of connect command
12333 */
12334 status = WLANTL_updateSpoofMacAddr(pHddCtx->pvosContext,
12335 &pHddCtx->spoofMacAddr.randomMacAddr, &pAdapter->macAddressCurrent);
12336 if (status != VOS_STATUS_SUCCESS)
12337 return -ECONNREFUSED;
12338 }
12339
12340 if ( req->channel )
12341 {
12342 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12343 req->ssid_len, req->bssid,
12344 req->bssid_hint,
12345 req->channel->hw_value);
12346 }
12347 else
12348 {
12349 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12350 req->ssid_len, req->bssid,
12351 req->bssid_hint, 0);
12352 }
12353
12354 if (0 != status)
12355 {
12356 //ReEnable BMPS if disabled
12357 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
12358 (NULL != pHddCtx))
12359 {
12360 if (pHddCtx->hdd_wlan_suspended)
12361 {
12362 hdd_set_pwrparams(pHddCtx);
12363 }
12364 //ReEnable Bmps and Imps back
12365 hdd_enable_bmps_imps(pHddCtx);
12366 }
12367 hddLog(VOS_TRACE_LEVEL_ERROR, FL("connect failed"));
12368 return status;
12369 }
12370 pHddCtx->isAmpAllowed = VOS_FALSE;
12371 EXIT();
12372 return status;
12373}
12374
12375static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
12376 struct net_device *ndev,
12377 struct cfg80211_connect_params *req)
12378{
12379 int ret;
12380 vos_ssr_protect(__func__);
12381 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12382 vos_ssr_unprotect(__func__);
12383
12384 return ret;
12385}
12386
12387/*
12388 * FUNCTION: wlan_hdd_disconnect
12389 * This function is used to issue a disconnect request to SME
12390 */
12391int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
12392{
12393 int status, result = 0;
12394 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12395 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12396 long ret;
12397
12398 ENTER();
12399
12400 status = wlan_hdd_validate_context(pHddCtx);
12401 if (0 != status)
12402 {
12403 return status;
12404 }
12405 /* Indicate sme of disconnect so that in progress connection or preauth
12406 * can be aborted
12407 */
12408 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
12409 pAdapter->sessionId);
12410 pHddCtx->isAmpAllowed = VOS_TRUE;
12411
12412 /* Need to apply spin lock before decreasing active sessions
12413 * as there can be chance for double decrement if context switch
12414 * Calls hdd_DisConnectHandler.
12415 */
12416
12417 spin_lock_bh(&pAdapter->lock_for_active_session);
12418 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
12419 {
12420 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
12421 }
12422 hdd_connSetConnectionState( pHddStaCtx, eConnectionState_Disconnecting );
12423 spin_unlock_bh(&pAdapter->lock_for_active_session);
12424
12425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12426 FL( "Set HDD connState to eConnectionState_Disconnecting" ));
12427
12428 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12429
12430 /*
12431 * stop tx queues before deleting STA/BSS context from the firmware.
12432 * tx has to be disabled because the firmware can get busy dropping
12433 * the tx frames after BSS/STA has been deleted and will not send
12434 * back a response resulting in WDI timeout
12435 */
12436 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
12437 netif_tx_disable(pAdapter->dev);
12438 netif_carrier_off(pAdapter->dev);
12439
12440 /*issue disconnect*/
12441 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
12442 pAdapter->sessionId, reason);
12443 if(eHAL_STATUS_CMD_NOT_QUEUED == status)
12444 {
12445 hddLog(VOS_TRACE_LEVEL_INFO,
12446 FL("status = %d, already disconnected"),
12447 (int)status );
12448
12449 }
12450 else if ( 0 != status )
12451 {
12452 hddLog(VOS_TRACE_LEVEL_ERROR,
12453 "%s csrRoamDisconnect failure, returned %d",
12454 __func__, (int)status );
12455 result = -EINVAL;
12456 goto disconnected;
12457 }
12458 ret = wait_for_completion_interruptible_timeout(
12459 &pAdapter->disconnect_comp_var,
12460 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
12461 if (!ret && ( eHAL_STATUS_CMD_NOT_QUEUED != status ))
12462 {
12463 hddLog(VOS_TRACE_LEVEL_ERROR,
12464 "%s: Failed to disconnect, timed out", __func__);
12465 result = -ETIMEDOUT;
12466 }
12467 else if (ret == -ERESTARTSYS)
12468 {
12469 hddLog(VOS_TRACE_LEVEL_ERROR,
12470 "%s: Failed to disconnect, wait interrupted", __func__);
12471 result = -ERESTARTSYS;
12472 }
12473disconnected:
12474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12475 FL("Set HDD connState to eConnectionState_NotConnected"));
12476 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
12477
12478 EXIT();
12479 return result;
12480}
12481
12482
12483/*
12484 * FUNCTION: __wlan_hdd_cfg80211_disconnect
12485 * This function is used to issue a disconnect request to SME
12486 */
12487static int __wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
12488 struct net_device *dev,
12489 u16 reason
12490 )
12491{
12492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
12493 int status;
12494 tCsrRoamProfile *pRoamProfile;
12495 hdd_station_ctx_t *pHddStaCtx;
12496 hdd_context_t *pHddCtx;
12497#ifdef FEATURE_WLAN_TDLS
12498 tANI_U8 staIdx;
12499#endif
12500
12501 ENTER();
12502
12503 if (!pAdapter) {
12504 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adpater is NULL"));
12505 return -EINVAL;
12506 }
12507
12508 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12509 if (!pHddStaCtx) {
12510 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD STA context is NULL"));
12511 return -EINVAL;
12512 }
12513
12514 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12515 status = wlan_hdd_validate_context(pHddCtx);
12516 if (0 != status)
12517 {
12518 return status;
12519 }
12520
12521 pRoamProfile = &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
12522
12523 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12524 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12525 pAdapter->sessionId, reason));
12526 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s(%d)",
12527 __func__, hdd_device_modetoString(pAdapter->device_mode),
12528 pAdapter->device_mode);
12529
12530 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
12531 __func__, reason);
12532
12533 if (NULL != pRoamProfile)
12534 {
12535 /*issue disconnect request to SME, if station is in connected state*/
12536 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12537 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting))
12538 {
12539 eCsrRoamDisconnectReason reasonCode =
12540 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12541 hdd_scaninfo_t *pScanInfo;
12542 switch(reason)
12543 {
12544 case WLAN_REASON_MIC_FAILURE:
12545 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12546 break;
12547
12548 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12549 case WLAN_REASON_DISASSOC_AP_BUSY:
12550 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12551 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12552 break;
12553
12554 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12555 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12556 case WLAN_REASON_DEAUTH_LEAVING:
12557 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12558 break;
12559
12560 default:
12561 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12562 break;
12563 }
12564 pScanInfo = &pHddCtx->scan_info;
12565 if (pScanInfo->mScanPending)
12566 {
12567 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
12568 "Aborting Scan");
12569 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
12570 eCSR_SCAN_ABORT_DEFAULT);
12571 }
12572 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
12573#ifdef FEATURE_WLAN_TDLS
12574 /* First clean up the tdls peers if any */
12575 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
12576 {
12577 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
12578 (pHddCtx->tdlsConnInfo[staIdx].staId))
12579 {
12580 uint8 *mac;
12581 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
12582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12583 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
12584 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
12585 MAC_ADDR_ARRAY(mac));
12586 status = sme_DeleteTdlsPeerSta(
12587 WLAN_HDD_GET_HAL_CTX(pAdapter),
12588 pAdapter->sessionId,
12589 mac);
12590 if (status != eHAL_STATUS_SUCCESS) {
12591 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to delete TDLS peer STA"));
12592 return -EPERM;
12593 }
12594 }
12595 }
12596#endif
12597 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"), reasonCode);
12598 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12599 if ( 0 != status )
12600 {
12601 hddLog(VOS_TRACE_LEVEL_ERROR,
12602 "%s wlan_hdd_disconnect failure, returned %d",
12603 __func__, (int)status );
12604 return -EINVAL;
12605 }
12606 }
12607 else
12608 {
12609 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unexpected cfg disconnect API"
12610 "called while in %d state", __func__,
12611 pHddStaCtx->conn_info.connState);
12612 }
12613 }
12614 else
12615 {
12616 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
12617 }
12618
12619 EXIT();
12620 return status;
12621}
12622
12623static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
12624 struct net_device *dev,
12625 u16 reason
12626 )
12627{
12628 int ret;
12629 vos_ssr_protect(__func__);
12630 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12631 vos_ssr_unprotect(__func__);
12632
12633 return ret;
12634}
12635
12636/*
12637 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
12638 * This function is used to initialize the security
12639 * settings in IBSS mode.
12640 */
12641static int wlan_hdd_cfg80211_set_privacy_ibss(
12642 hdd_adapter_t *pAdapter,
12643 struct cfg80211_ibss_params *params
12644 )
12645{
12646 int status = 0;
12647 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12648 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12649 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12650
12651 ENTER();
12652
12653 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12654 vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
12655
12656 if (params->ie_len && ( NULL != params->ie) )
12657 {
12658 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
12659 params->ie_len, WLAN_EID_RSN ))
12660 {
12661 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12662 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12663 }
12664 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
12665 {
12666 tDot11fIEWPA dot11WPAIE;
12667 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12668 u8 *ie;
12669
12670 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12671 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
12672 params->ie_len, DOT11F_EID_WPA);
12673 if ( NULL != ie )
12674 {
12675 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12676 // Unpack the WPA IE
12677 //Skip past the EID byte and length byte - and four byte WiFi OUI
12678 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
12679 &ie[2+4],
12680 ie[1] - 4,
12681 &dot11WPAIE);
12682 /*Extract the multicast cipher, the encType for unicast
12683 cipher for wpa-none is none*/
12684 encryptionType =
12685 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
12686 }
12687 }
12688
12689 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
12690
12691 if (0 > status)
12692 {
12693 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
12694 __func__);
12695 return status;
12696 }
12697 }
12698
12699 pWextState->roamProfile.AuthType.authType[0] =
12700 pHddStaCtx->conn_info.authType =
12701 eCSR_AUTH_TYPE_OPEN_SYSTEM;
12702
12703 if (params->privacy)
12704 {
12705 /* Security enabled IBSS, At this time there is no information available
12706 * about the security paramters, so initialise the encryption type to
12707 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12708 * The correct security parameters will be updated later in
12709 * wlan_hdd_cfg80211_add_key */
12710 /* Hal expects encryption type to be set inorder
12711 *enable privacy bit in beacons */
12712
12713 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12714 }
12715 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
12716 "encryptionType=%d", encryptionType);
12717 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12718 pWextState->roamProfile.EncryptionType.numEntries = 1;
12719 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
12720 return status;
12721}
12722
12723/*
12724 * FUNCTION: __wlan_hdd_cfg80211_join_ibss
12725 * This function is used to create/join an IBSS
12726 */
12727static int __wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
12728 struct net_device *dev,
12729 struct cfg80211_ibss_params *params
12730 )
12731{
12732 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
12733 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12734 tCsrRoamProfile *pRoamProfile;
12735 int status;
12736 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12737 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12738 tSirMacAddr bssid;
12739
12740 ENTER();
12741
12742 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12743 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12744 pAdapter->sessionId, pAdapter->device_mode));
12745 hddLog(VOS_TRACE_LEVEL_INFO,
12746 "%s: device_mode = %s (%d)", __func__,
12747 hdd_device_modetoString(pAdapter->device_mode),
12748 pAdapter->device_mode);
12749
12750 status = wlan_hdd_validate_context(pHddCtx);
12751 if (0 != status)
12752 {
12753 return status;
12754 }
12755
12756 if (NULL == pWextState)
12757 {
12758 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
12759 __func__);
12760 return -EIO;
12761 }
12762
12763 if (vos_max_concurrent_connections_reached()) {
12764 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
12765 return -ECONNREFUSED;
12766 }
12767
12768 /*Try disconnecting if already in connected state*/
12769 status = wlan_hdd_try_disconnect(pAdapter);
12770 if ( 0 > status)
12771 {
12772 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
12773 " IBSS connection"));
12774 return -EALREADY;
12775 }
12776
12777 pRoamProfile = &pWextState->roamProfile;
12778
12779 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
12780 {
12781 hddLog (VOS_TRACE_LEVEL_ERROR,
12782 "%s Interface type is not set to IBSS", __func__);
12783 return -EINVAL;
12784 }
12785
12786 /* BSSID is provided by upper layers hence no need to AUTO generate */
12787 if (NULL != params->bssid) {
12788 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
12789 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) {
12790 hddLog (VOS_TRACE_LEVEL_ERROR,
12791 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
12792 return -EIO;
12793 }
12794 vos_mem_copy((v_U8_t *)bssid, (v_U8_t *)params->bssid, sizeof(bssid));
12795 }
12796 else if(pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0)
12797 {
12798 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
12799 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
12800 {
12801 hddLog (VOS_TRACE_LEVEL_ERROR,
12802 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
12803 return -EIO;
12804 }
12805
12806 vos_mem_copy((v_U8_t *)bssid,
12807 (v_U8_t *)&pHddCtx->cfg_ini->IbssBssid.bytes[0],
12808 sizeof(bssid));
12809 }
12810
12811 /* Set Channel */
12812 if (NULL !=
12813#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
12814 params->chandef.chan)
12815#else
12816 params->channel)
12817#endif
12818 {
12819 u8 channelNum;
12820 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12821 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12822 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12823 int indx;
12824
12825 /* Get channel number */
12826 channelNum =
12827 ieee80211_frequency_to_channel(
12828#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
12829 params->chandef.chan->center_freq);
12830#else
12831 params->channel->center_freq);
12832#endif
12833
12834 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12835 validChan, &numChans))
12836 {
12837 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
12838 __func__);
12839 return -EOPNOTSUPP;
12840 }
12841
12842 for (indx = 0; indx < numChans; indx++)
12843 {
12844 if (channelNum == validChan[indx])
12845 {
12846 break;
12847 }
12848 }
12849 if (indx >= numChans)
12850 {
12851 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
12852 __func__, channelNum);
12853 return -EINVAL;
12854 }
12855 /* Set the Operational Channel */
12856 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
12857 channelNum);
12858 pRoamProfile->ChannelInfo.numOfChannels = 1;
12859 pHddStaCtx->conn_info.operationChannel = channelNum;
12860 pRoamProfile->ChannelInfo.ChannelList =
12861 &pHddStaCtx->conn_info.operationChannel;
12862 }
12863
12864 /* Initialize security parameters */
12865 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12866 if (status < 0)
12867 {
12868 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
12869 __func__);
12870 return status;
12871 }
12872
12873 /* Issue connect start */
12874 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12875 params->ssid_len, (const u8 *)&bssid, NULL,
12876 pHddStaCtx->conn_info.operationChannel);
12877
12878 if (0 > status)
12879 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
12880
12881 EXIT();
12882 return status;
12883}
12884
12885static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
12886 struct net_device *dev,
12887 struct cfg80211_ibss_params *params
12888 )
12889{
12890 int ret = 0;
12891
12892 vos_ssr_protect(__func__);
12893 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12894 vos_ssr_unprotect(__func__);
12895
12896 return ret;
12897}
12898
12899/*
12900 * FUNCTION: __wlan_hdd_cfg80211_leave_ibss
12901 * This function is used to leave an IBSS
12902 */
12903static int __wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
12904 struct net_device *dev
12905 )
12906{
12907 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
12908 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12909 tCsrRoamProfile *pRoamProfile;
12910 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12911 int status;
12912
12913 ENTER();
12914
12915 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12916 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12917 pAdapter->sessionId, eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12918 status = wlan_hdd_validate_context(pHddCtx);
12919 if (0 != status)
12920 {
12921 return status;
12922 }
12923
12924 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)", __func__,
12925 hdd_device_modetoString(pAdapter->device_mode),
12926 pAdapter->device_mode);
12927 if (NULL == pWextState)
12928 {
12929 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
12930 __func__);
12931 return -EIO;
12932 }
12933
12934 pRoamProfile = &pWextState->roamProfile;
12935
12936 /* Issue disconnect only if interface type is set to IBSS */
12937 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
12938 {
12939 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
12940 __func__);
12941 return -EINVAL;
12942 }
12943
12944 /* Issue Disconnect request */
12945 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12946 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
12947 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
12948
12949 EXIT();
12950 return 0;
12951}
12952
12953static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
12954 struct net_device *dev
12955 )
12956{
12957 int ret = 0;
12958
12959 vos_ssr_protect(__func__);
12960 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
12961 vos_ssr_unprotect(__func__);
12962
12963 return ret;
12964}
12965
12966/*
12967 * FUNCTION: __wlan_hdd_cfg80211_set_wiphy_params
12968 * This function is used to set the phy parameters
12969 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
12970 */
12971static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
12972 u32 changed)
12973{
12974 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
12975 tHalHandle hHal = pHddCtx->hHal;
12976 int status;
12977
12978 ENTER();
12979
12980 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12981 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
12982 NO_SESSION, wiphy->rts_threshold));
12983
12984 status = wlan_hdd_validate_context(pHddCtx);
12985 if (0 != status)
12986 {
12987 return status;
12988 }
12989
12990 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
12991 {
12992 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
12993 WNI_CFG_RTS_THRESHOLD_STAMAX :
12994 wiphy->rts_threshold;
12995
12996 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
12997 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
12998 {
12999 hddLog(VOS_TRACE_LEVEL_ERROR,
13000 "%s: Invalid RTS Threshold value %hu",
13001 __func__, rts_threshold);
13002 return -EINVAL;
13003 }
13004
13005 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
13006 rts_threshold, ccmCfgSetCallback,
13007 eANI_BOOLEAN_TRUE))
13008 {
13009 hddLog(VOS_TRACE_LEVEL_ERROR,
13010 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
13011 __func__, rts_threshold);
13012 return -EIO;
13013 }
13014
13015 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
13016 rts_threshold);
13017 }
13018
13019 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
13020 {
13021 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13022 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13023 wiphy->frag_threshold;
13024
13025 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
13026 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
13027 {
13028 hddLog(VOS_TRACE_LEVEL_ERROR,
13029 "%s: Invalid frag_threshold value %hu", __func__,
13030 frag_threshold);
13031 return -EINVAL;
13032 }
13033
13034 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13035 frag_threshold, ccmCfgSetCallback,
13036 eANI_BOOLEAN_TRUE))
13037 {
13038 hddLog(VOS_TRACE_LEVEL_ERROR,
13039 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
13040 __func__, frag_threshold);
13041 return -EIO;
13042 }
13043
13044 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
13045 frag_threshold);
13046 }
13047
13048 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13049 || (changed & WIPHY_PARAM_RETRY_LONG))
13050 {
13051 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13052 wiphy->retry_short :
13053 wiphy->retry_long;
13054
13055 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13056 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
13057 {
13058 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
13059 __func__, retry_value);
13060 return -EINVAL;
13061 }
13062
13063 if (changed & WIPHY_PARAM_RETRY_SHORT)
13064 {
13065 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
13066 retry_value, ccmCfgSetCallback,
13067 eANI_BOOLEAN_TRUE))
13068 {
13069 hddLog(VOS_TRACE_LEVEL_ERROR,
13070 "%s: ccmCfgSetInt failed for long retry count %hu",
13071 __func__, retry_value);
13072 return -EIO;
13073 }
13074 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
13075 __func__, retry_value);
13076 }
13077 else if (changed & WIPHY_PARAM_RETRY_SHORT)
13078 {
13079 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
13080 retry_value, ccmCfgSetCallback,
13081 eANI_BOOLEAN_TRUE))
13082 {
13083 hddLog(VOS_TRACE_LEVEL_ERROR,
13084 "%s: ccmCfgSetInt failed for short retry count %hu",
13085 __func__, retry_value);
13086 return -EIO;
13087 }
13088 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
13089 __func__, retry_value);
13090 }
13091 }
13092
13093 EXIT();
13094 return 0;
13095}
13096
13097static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13098 u32 changed)
13099{
13100 int ret;
13101
13102 vos_ssr_protect(__func__);
13103 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13104 vos_ssr_unprotect(__func__);
13105
13106 return ret;
13107}
13108
13109/*
13110 * FUNCTION: __wlan_hdd_cfg80211_set_txpower
13111 * This function is used to set the txpower
13112 */
13113static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
13114#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
13115 struct wireless_dev *wdev,
13116#endif
13117#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
13118 enum tx_power_setting type,
13119#else
13120 enum nl80211_tx_power_setting type,
13121#endif
13122 int dbm)
13123{
13124 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
13125 tHalHandle hHal = NULL;
13126 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
13127 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
13128 int status;
13129
13130 ENTER();
13131
13132 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
13133 TRACE_CODE_HDD_CFG80211_SET_TXPOWER,
13134 NO_SESSION, type ));
13135 status = wlan_hdd_validate_context(pHddCtx);
13136 if (0 != status)
13137 {
13138 return status;
13139 }
13140
13141 hHal = pHddCtx->hHal;
13142
13143 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
13144 dbm, ccmCfgSetCallback,
13145 eANI_BOOLEAN_TRUE))
13146 {
13147 hddLog(VOS_TRACE_LEVEL_ERROR,
13148 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
13149 return -EIO;
13150 }
13151
13152 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
13153 dbm);
13154
13155 switch(type)
13156 {
13157 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
13158 /* Fall through */
13159 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
13160 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
13161 {
13162 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
13163 __func__);
13164 return -EIO;
13165 }
13166 break;
13167 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
13168 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
13169 __func__);
13170 return -EOPNOTSUPP;
13171 break;
13172 default:
13173 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
13174 __func__, type);
13175 return -EIO;
13176 }
13177
13178 EXIT();
13179 return 0;
13180}
13181
13182static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
13183#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
13184 struct wireless_dev *wdev,
13185#endif
13186#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
13187 enum tx_power_setting type,
13188#else
13189 enum nl80211_tx_power_setting type,
13190#endif
13191 int dbm)
13192{
13193 int ret;
13194 vos_ssr_protect(__func__);
13195 ret = __wlan_hdd_cfg80211_set_txpower(wiphy,
13196#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
13197 wdev,
13198#endif
13199#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
13200 type,
13201#else
13202 type,
13203#endif
13204 dbm);
13205 vos_ssr_unprotect(__func__);
13206
13207 return ret;
13208}
13209
13210/*
13211 * FUNCTION: __wlan_hdd_cfg80211_get_txpower
13212 * This function is used to read the txpower
13213 */
13214static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
13215#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
13216 struct wireless_dev *wdev,
13217#endif
13218 int *dbm)
13219{
13220
13221 hdd_adapter_t *pAdapter;
13222 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
13223 int status;
13224
13225 ENTER();
13226
13227 status = wlan_hdd_validate_context(pHddCtx);
13228 if (0 != status)
13229 {
13230 *dbm = 0;
13231 return status;
13232 }
13233
13234 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
13235 if (NULL == pAdapter)
13236 {
13237 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
13238 return -ENOENT;
13239 }
13240
13241 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
13242 TRACE_CODE_HDD_CFG80211_GET_TXPOWER,
13243 pAdapter->sessionId, pAdapter->device_mode));
13244 wlan_hdd_get_classAstats(pAdapter);
13245 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
13246
13247 EXIT();
13248 return 0;
13249}
13250
13251static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
13252#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
13253 struct wireless_dev *wdev,
13254#endif
13255 int *dbm)
13256{
13257 int ret;
13258
13259 vos_ssr_protect(__func__);
13260 ret = __wlan_hdd_cfg80211_get_txpower(wiphy,
13261#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
13262 wdev,
13263#endif
13264 dbm);
13265 vos_ssr_unprotect(__func__);
13266
13267 return ret;
13268}
13269
13270static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
13271#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
13272 const u8* mac,
13273#else
13274 u8* mac,
13275#endif
13276 struct station_info *sinfo)
13277{
13278 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
13279 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13280 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
13281 tANI_U32 rate_flags;
13282
13283 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
13284 hdd_config_t *pCfg = pHddCtx->cfg_ini;
13285
13286 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
13287 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
13288 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
13289 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
13290 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
13291 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
13292 tANI_U16 maxRate = 0;
13293 tANI_U16 myRate;
13294 tANI_U16 currentRate = 0;
13295 tANI_U8 maxSpeedMCS = 0;
13296 tANI_U8 maxMCSIdx = 0;
13297 tANI_U8 rateFlag = 1;
13298 tANI_U8 i, j, rssidx, mode=0;
13299 tANI_U16 temp;
13300 int status;
13301
13302#ifdef WLAN_FEATURE_11AC
13303 tANI_U32 vht_mcs_map;
13304 eDataRate11ACMaxMcs vhtMaxMcs;
13305#endif /* WLAN_FEATURE_11AC */
13306
13307 ENTER();
13308
13309 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
13310 (0 == ssidlen))
13311 {
13312 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
13313 " Invalid ssidlen, %d", __func__, ssidlen);
13314 /*To keep GUI happy*/
13315 return 0;
13316 }
13317
13318 if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario)
13319 {
13320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13321 "%s: Roaming in progress, so unable to proceed this request", __func__);
13322 return 0;
13323 }
13324
13325 status = wlan_hdd_validate_context(pHddCtx);
13326 if (0 != status)
13327 {
13328 return status;
13329 }
13330
13331 wlan_hdd_get_station_stats(pAdapter);
13332 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
13333
13334 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
13335 sinfo->filled |= STATION_INFO_SIGNAL;
13336
13337 /*overwrite rate_flags if MAX link-speed need to be reported*/
13338 if ((eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed) ||
13339 (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed &&
13340 sinfo->signal >= pCfg->linkSpeedRssiLow))
13341 {
13342 rate_flags = pAdapter->maxRateFlags;
13343 }
13344
13345 //convert to the UI units of 100kbps
13346 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
13347
13348#ifdef LINKSPEED_DEBUG_ENABLED
13349 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
13350 sinfo->signal,
13351 pCfg->reportMaxLinkSpeed,
13352 myRate,
13353 (int) pCfg->linkSpeedRssiHigh,
13354 (int) pCfg->linkSpeedRssiMid,
13355 (int) pCfg->linkSpeedRssiLow,
13356 (int) rate_flags,
13357 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
13358#endif //LINKSPEED_DEBUG_ENABLED
13359
13360 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
13361 {
13362 // we do not want to necessarily report the current speed
13363 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
13364 {
13365 // report the max possible speed
13366 rssidx = 0;
13367 }
13368 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
13369 {
13370 // report the max possible speed with RSSI scaling
13371 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
13372 {
13373 // report the max possible speed
13374 rssidx = 0;
13375 }
13376 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
13377 {
13378 // report middle speed
13379 rssidx = 1;
13380 }
13381 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
13382 {
13383 // report middle speed
13384 rssidx = 2;
13385 }
13386 else
13387 {
13388 // report actual speed
13389 rssidx = 3;
13390 }
13391 }
13392 else
13393 {
13394 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
13395 hddLog(VOS_TRACE_LEVEL_ERROR,
13396 "%s: Invalid value for reportMaxLinkSpeed: %u",
13397 __func__, pCfg->reportMaxLinkSpeed);
13398 rssidx = 0;
13399 }
13400
13401 maxRate = 0;
13402
13403 /* Get Basic Rate Set */
13404 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
13405 OperationalRates, &ORLeng))
13406 {
13407 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
13408 /*To keep GUI happy*/
13409 return 0;
13410 }
13411
13412 for (i = 0; i < ORLeng; i++)
13413 {
13414 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
13415 {
13416 /* Validate Rate Set */
13417 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
13418 {
13419 currentRate = supported_data_rate[j].supported_rate[rssidx];
13420 break;
13421 }
13422 }
13423 /* Update MAX rate */
13424 maxRate = (currentRate > maxRate)?currentRate:maxRate;
13425 }
13426
13427 /* Get Extended Rate Set */
13428 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
13429 ExtendedRates, &ERLeng))
13430 {
13431 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
13432 /*To keep GUI happy*/
13433 return 0;
13434 }
13435
13436 for (i = 0; i < ERLeng; i++)
13437 {
13438 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
13439 {
13440 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
13441 {
13442 currentRate = supported_data_rate[j].supported_rate[rssidx];
13443 break;
13444 }
13445 }
13446 /* Update MAX rate */
13447 maxRate = (currentRate > maxRate)?currentRate:maxRate;
13448 }
13449
13450 /* Get MCS Rate Set --
13451 Only if we are always reporting max speed (or)
13452 if we have good rssi */
13453 if ((3 != rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
13454 {
13455 if (rate_flags & eHAL_TX_RATE_VHT80)
13456 mode = 2;
13457 else if (rate_flags & (eHAL_TX_RATE_VHT40 | eHAL_TX_RATE_HT40))
13458 mode = 1;
13459 else
13460 mode = 0;
13461
13462 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
13463 MCSRates, &MCSLeng))
13464 {
13465 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
13466 /*To keep GUI happy*/
13467 return 0;
13468 }
13469 rateFlag = 0;
13470#ifdef WLAN_FEATURE_11AC
13471 /* VHT80 rate has seperate rate table */
13472 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
13473 {
13474 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
13475 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
13476 if (rate_flags & eHAL_TX_RATE_SGI)
13477 {
13478 rateFlag |= 1;
13479 }
13480 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
13481 {
13482 maxMCSIdx = 7;
13483 }
13484 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
13485 {
13486 maxMCSIdx = 8;
13487 }
13488 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
13489 {
13490 //VHT20 is supporting 0~8
13491 if (rate_flags & eHAL_TX_RATE_VHT20)
13492 maxMCSIdx = 8;
13493 else
13494 maxMCSIdx = 9;
13495 }
13496
13497 if (0 != rssidx)/*check for scaled */
13498 {
13499 //get middle rate MCS index if rssi=1/2
13500 for (i=0; i <= maxMCSIdx; i++)
13501 {
13502 if (sinfo->signal <= rssiMcsTbl[mode][i])
13503 {
13504 maxMCSIdx = i;
13505 break;
13506 }
13507 }
13508 }
13509
13510 if (rate_flags & eHAL_TX_RATE_VHT80)
13511 {
13512 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
13513 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
13514 }
13515 else if (rate_flags & eHAL_TX_RATE_VHT40)
13516 {
13517 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
13518 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
13519 }
13520 else if (rate_flags & eHAL_TX_RATE_VHT20)
13521 {
13522 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
13523 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
13524 }
13525
13526 maxSpeedMCS = 1;
13527 if (currentRate > maxRate)
13528 {
13529 maxRate = currentRate;
13530 }
13531
13532 }
13533 else
13534#endif /* WLAN_FEATURE_11AC */
13535 {
13536 if (rate_flags & eHAL_TX_RATE_HT40)
13537 {
13538 rateFlag |= 1;
13539 }
13540 if (rate_flags & eHAL_TX_RATE_SGI)
13541 {
13542 rateFlag |= 2;
13543 }
13544
13545 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
13546 if (rssidx == 1 || rssidx == 2)
13547 {
13548 //get middle rate MCS index if rssi=1/2
13549 for (i=0; i <= 7; i++)
13550 {
13551 if (sinfo->signal <= rssiMcsTbl[mode][i])
13552 {
13553 temp = i+1;
13554 break;
13555 }
13556 }
13557 }
13558
13559 for (i = 0; i < MCSLeng; i++)
13560 {
13561 for (j = 0; j < temp; j++)
13562 {
13563 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
13564 {
13565 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
13566 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
13567 break;
13568 }
13569 }
13570 if ((j < temp) && (currentRate > maxRate))
13571 {
13572 maxRate = currentRate;
13573 }
13574 }
13575 maxSpeedMCS = 1;
13576 }
13577 }
13578
13579 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
13580 {
13581 maxRate = myRate;
13582 maxSpeedMCS = 1;
13583 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
13584 }
13585 // make sure we report a value at least as big as our current rate
13586 if ((maxRate < myRate) || (0 == maxRate))
13587 {
13588 maxRate = myRate;
13589 if (rate_flags & eHAL_TX_RATE_LEGACY)
13590 {
13591 maxSpeedMCS = 0;
13592 }
13593 else
13594 {
13595 maxSpeedMCS = 1;
13596 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
13597 }
13598 }
13599
13600 if (rate_flags & eHAL_TX_RATE_LEGACY)
13601 {
13602 sinfo->txrate.legacy = maxRate;
13603#ifdef LINKSPEED_DEBUG_ENABLED
13604 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
13605#endif //LINKSPEED_DEBUG_ENABLED
13606 }
13607 else
13608 {
13609 sinfo->txrate.mcs = maxMCSIdx;
13610#ifdef WLAN_FEATURE_11AC
13611 sinfo->txrate.nss = 1;
13612 if (rate_flags & eHAL_TX_RATE_VHT80)
13613 {
13614 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
13615 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
13616 }
13617 else if (rate_flags & eHAL_TX_RATE_VHT40)
13618 {
13619 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
13620 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
13621 }
13622 else if (rate_flags & eHAL_TX_RATE_VHT20)
13623 {
13624 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
13625 }
13626#endif /* WLAN_FEATURE_11AC */
13627 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
13628 {
13629 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
13630 if (rate_flags & eHAL_TX_RATE_HT40)
13631 {
13632 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
13633 }
13634 }
13635 if (rate_flags & eHAL_TX_RATE_SGI)
13636 {
13637 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
13638 }
13639
13640#ifdef LINKSPEED_DEBUG_ENABLED
13641 pr_info("Reporting MCS rate %d flags %x\n",
13642 sinfo->txrate.mcs,
13643 sinfo->txrate.flags );
13644#endif //LINKSPEED_DEBUG_ENABLED
13645 }
13646 }
13647 else
13648 {
13649 // report current rate instead of max rate
13650
13651 if (rate_flags & eHAL_TX_RATE_LEGACY)
13652 {
13653 //provide to the UI in units of 100kbps
13654 sinfo->txrate.legacy = myRate;
13655#ifdef LINKSPEED_DEBUG_ENABLED
13656 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
13657#endif //LINKSPEED_DEBUG_ENABLED
13658 }
13659 else
13660 {
13661 //must be MCS
13662 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
13663#ifdef WLAN_FEATURE_11AC
13664 sinfo->txrate.nss = 1;
13665 if (rate_flags & eHAL_TX_RATE_VHT80)
13666 {
13667 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
13668 }
13669 else
13670#endif /* WLAN_FEATURE_11AC */
13671 {
13672 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
13673 }
13674 if (rate_flags & eHAL_TX_RATE_SGI)
13675 {
13676 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
13677 }
13678 if (rate_flags & eHAL_TX_RATE_HT40)
13679 {
13680 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
13681 }
13682#ifdef WLAN_FEATURE_11AC
13683 else if (rate_flags & eHAL_TX_RATE_VHT80)
13684 {
13685 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
13686 }
13687#endif /* WLAN_FEATURE_11AC */
13688#ifdef LINKSPEED_DEBUG_ENABLED
13689 pr_info("Reporting actual MCS rate %d flags %x\n",
13690 sinfo->txrate.mcs,
13691 sinfo->txrate.flags );
13692#endif //LINKSPEED_DEBUG_ENABLED
13693 }
13694 }
13695 sinfo->filled |= STATION_INFO_TX_BITRATE;
13696
13697 sinfo->tx_packets =
13698 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
13699 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
13700 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
13701 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
13702
13703 sinfo->tx_retries =
13704 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
13705 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
13706 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
13707 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
13708
13709 sinfo->tx_failed =
13710 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
13711 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
13712 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
13713 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
13714
13715 sinfo->filled |=
13716 STATION_INFO_TX_PACKETS |
13717 STATION_INFO_TX_RETRIES |
13718 STATION_INFO_TX_FAILED;
13719
13720 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
13721 TRACE_CODE_HDD_CFG80211_GET_STA,
13722 pAdapter->sessionId, maxRate));
13723 EXIT();
13724 return 0;
13725}
13726#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
13727static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
13728 const u8* mac, struct station_info *sinfo)
13729#else
13730static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
13731 u8* mac, struct station_info *sinfo)
13732#endif
13733{
13734 int ret;
13735
13736 vos_ssr_protect(__func__);
13737 ret = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo);
13738 vos_ssr_unprotect(__func__);
13739
13740 return ret;
13741}
13742
13743static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
13744 struct net_device *dev, bool mode, int timeout)
13745{
13746 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13747 hdd_context_t *pHddCtx;
13748 VOS_STATUS vos_status;
13749 int status;
13750
13751 ENTER();
13752
13753 if (NULL == pAdapter)
13754 {
13755 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
13756 return -ENODEV;
13757 }
13758
13759 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
13760 TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT,
13761 pAdapter->sessionId, timeout));
13762
13763 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13764 status = wlan_hdd_validate_context(pHddCtx);
13765 if (0 != status)
13766 {
13767 return status;
13768 }
13769
13770 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
13771 (TRUE == pHddCtx->hdd_wlan_suspended) &&
13772 (pHddCtx->cfg_ini->fhostArpOffload) &&
13773 (eConnectionState_Associated ==
13774 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
13775 {
13776
13777 hddLog(VOS_TRACE_LEVEL_INFO,
13778 "offload: in cfg80211_set_power_mgmt, calling arp offload");
13779 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
13780 if (!VOS_IS_STATUS_SUCCESS(vos_status))
13781 {
13782 hddLog(VOS_TRACE_LEVEL_INFO,
13783 "%s:Failed to enable ARPOFFLOAD Feature %d",
13784 __func__, vos_status);
13785 }
13786 }
13787
13788 /**The get power cmd from the supplicant gets updated by the nl only
13789 *on successful execution of the function call
13790 *we are oppositely mapped w.r.t mode in the driver
13791 **/
13792 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
13793
13794 if (VOS_STATUS_E_FAILURE == vos_status)
13795 {
13796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13797 "%s: failed to enter bmps mode", __func__);
13798 return -EINVAL;
13799 }
13800 EXIT();
13801 return 0;
13802}
13803
13804static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
13805 struct net_device *dev, bool mode, int timeout)
13806{
13807 int ret;
13808
13809 vos_ssr_protect(__func__);
13810 ret = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, mode, timeout);
13811 vos_ssr_unprotect(__func__);
13812
13813 return ret;
13814}
13815#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
13816static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13817 struct net_device *netdev,
13818 u8 key_index)
13819{
13820 ENTER();
13821 return 0;
13822}
13823
13824static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13825 struct net_device *netdev,
13826 u8 key_index)
13827{
13828 int ret;
13829 vos_ssr_protect(__func__);
13830 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13831 vos_ssr_unprotect(__func__);
13832 return ret;
13833}
13834#endif //LINUX_VERSION_CODE
13835
13836#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
13837static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13838 struct net_device *dev,
13839 struct ieee80211_txq_params *params)
13840{
13841 ENTER();
13842 return 0;
13843}
13844#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
13845static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13846 struct ieee80211_txq_params *params)
13847{
13848 ENTER();
13849 return 0;
13850}
13851#endif //LINUX_VERSION_CODE
13852
13853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
13854static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13855 struct net_device *dev,
13856 struct ieee80211_txq_params *params)
13857{
13858 int ret;
13859
13860 vos_ssr_protect(__func__);
13861 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13862 vos_ssr_unprotect(__func__);
13863 return ret;
13864}
13865#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
13866static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13867 struct ieee80211_txq_params *params)
13868{
13869 int ret;
13870
13871 vos_ssr_protect(__func__);
13872 ret = __wlan_hdd_set_txq_params(wiphy, params);
13873 vos_ssr_unprotect(__func__);
13874 return ret;
13875}
13876#endif
13877
13878static int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13879 struct net_device *dev,
13880 struct tagCsrDelStaParams *pDelStaParams)
13881{
13882 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13883 hdd_context_t *pHddCtx;
13884 VOS_STATUS vos_status;
13885 int status;
13886 v_U8_t staId;
13887 v_CONTEXT_t pVosContext = NULL;
13888 ptSapContext pSapCtx = NULL;
13889
13890 ENTER();
13891
13892 if ( NULL == pAdapter )
13893 {
13894 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
13895 return -EINVAL;
13896 }
13897
13898 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
13899 TRACE_CODE_HDD_CFG80211_DEL_STA,
13900 pAdapter->sessionId, pAdapter->device_mode));
13901
13902 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13903 status = wlan_hdd_validate_context(pHddCtx);
13904 if (0 != status)
13905 {
13906 return status;
13907 }
13908
13909 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
13910 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
13911 )
13912 {
13913 pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13914 pSapCtx = VOS_GET_SAP_CB(pVosContext);
13915 if(pSapCtx == NULL){
13916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13917 FL("psapCtx is NULL"));
13918 return -ENOENT;
13919 }
13920 if (vos_is_macaddr_broadcast((v_MACADDR_t *)pDelStaParams->peerMacAddr))
13921 {
13922 v_U16_t i;
13923 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
13924 {
13925 if ((pSapCtx->aStaInfo[i].isUsed) &&
13926 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
13927 {
13928 vos_mem_copy(pDelStaParams->peerMacAddr,
13929 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
13930 ETHER_ADDR_LEN);
13931
13932 hddLog(VOS_TRACE_LEVEL_INFO,
13933 "%s: Delete STA with MAC::"
13934 MAC_ADDRESS_STR,
13935 __func__,
13936 MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr));
13937 vos_status = hdd_softap_sta_deauth(pAdapter, pDelStaParams);
13938 if (VOS_IS_STATUS_SUCCESS(vos_status))
13939 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
13940 }
13941 }
13942 }
13943 else
13944 {
13945
13946 vos_status = hdd_softap_GetStaId(pAdapter,
13947 (v_MACADDR_t *)pDelStaParams->peerMacAddr, &staId);
13948 if (!VOS_IS_STATUS_SUCCESS(vos_status))
13949 {
13950 hddLog(VOS_TRACE_LEVEL_INFO,
13951 "%s: Skip this DEL STA as this is not used::"
13952 MAC_ADDRESS_STR,
13953 __func__, MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr));
13954 return -ENOENT;
13955 }
13956
13957 if( pSapCtx->aStaInfo[staId].isDeauthInProgress == TRUE)
13958 {
13959 hddLog(VOS_TRACE_LEVEL_INFO,
13960 "%s: Skip this DEL STA as deauth is in progress::"
13961 MAC_ADDRESS_STR,
13962 __func__, MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr));
13963 return -ENOENT;
13964 }
13965
13966 pSapCtx->aStaInfo[staId].isDeauthInProgress = TRUE;
13967
13968 hddLog(VOS_TRACE_LEVEL_INFO,
13969 "%s: Delete STA with MAC::"
13970 MAC_ADDRESS_STR,
13971 __func__,
13972 MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr));
13973
13974 vos_status = hdd_softap_sta_deauth(pAdapter, pDelStaParams);
13975 if (!VOS_IS_STATUS_SUCCESS(vos_status))
13976 {
13977 pSapCtx->aStaInfo[staId].isDeauthInProgress = FALSE;
13978 hddLog(VOS_TRACE_LEVEL_INFO,
13979 "%s: STA removal failed for ::"
13980 MAC_ADDRESS_STR,
13981 __func__,
13982 MAC_ADDR_ARRAY(pDelStaParams->peerMacAddr));
13983 return -ENOENT;
13984 }
13985
13986 }
13987 }
13988
13989 EXIT();
13990
13991 return 0;
13992}
13993
13994#ifdef CFG80211_DEL_STA_V2
13995static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13996 struct net_device *dev,
13997 struct station_del_parameters *param)
13998#else
13999#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
14000static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14001 struct net_device *dev, const u8 *mac)
14002#else
14003static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14004 struct net_device *dev, u8 *mac)
14005#endif
14006#endif
14007{
14008 int ret;
14009 struct tagCsrDelStaParams delStaParams;
14010
14011 vos_ssr_protect(__func__);
14012
14013#ifdef CFG80211_DEL_STA_V2
14014 if (NULL == param) {
14015 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid argumet passed", __func__);
14016 vos_ssr_unprotect(__func__);
14017 return -EINVAL;
14018 }
14019
14020 WLANSAP_PopulateDelStaParams(param->mac, param->reason_code,
14021 param->subtype, &delStaParams);
14022
14023#else
14024 WLANSAP_PopulateDelStaParams(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14025 (SIR_MAC_MGMT_DEAUTH >> 4), &delStaParams);
14026#endif
14027 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14028
14029 vos_ssr_unprotect(__func__);
14030
14031 return ret;
14032}
14033
14034static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14035 struct net_device *dev,
14036#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
14037 const u8 *mac,
14038#else
14039 u8 *mac,
14040#endif
14041 struct station_parameters *params)
14042{
14043 hdd_adapter_t *pAdapter;
14044 hdd_context_t *pHddCtx;
14045 int status = -EPERM;
14046#ifdef FEATURE_WLAN_TDLS
14047 u32 mask, set;
14048
14049 ENTER();
14050
14051 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14052 if (NULL == pAdapter)
14053 {
14054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14055 "%s: Adapter is NULL",__func__);
14056 return -EINVAL;
14057 }
14058 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14059 status = wlan_hdd_validate_context(pHddCtx);
14060 if (0 != status)
14061 {
14062 return status;
14063 }
14064
14065 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
14066 TRACE_CODE_HDD_CFG80211_ADD_STA,
14067 pAdapter->sessionId, params->listen_interval));
14068 mask = params->sta_flags_mask;
14069
14070 set = params->sta_flags_set;
14071
14072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14073 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
14074 __func__, mask, set, MAC_ADDR_ARRAY(mac));
14075
14076 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14077 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14078 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14079 }
14080 }
14081#endif
14082 EXIT();
14083 return status;
14084}
14085
14086#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
14087static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14088 struct net_device *dev, const u8 *mac,
14089 struct station_parameters *params)
14090#else
14091static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14092 struct net_device *dev, u8 *mac, struct station_parameters *params)
14093#endif
14094{
14095 int ret;
14096
14097 vos_ssr_protect(__func__);
14098 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14099 vos_ssr_unprotect(__func__);
14100
14101 return ret;
14102}
14103#ifdef FEATURE_WLAN_LFR
14104
14105static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
14106 struct cfg80211_pmksa *pmksa)
14107{
14108 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14109 tHalHandle halHandle;
14110 eHalStatus result;
14111 int status;
14112 hdd_context_t *pHddCtx;
14113 tPmkidCacheInfo pmk_id;
14114
14115 ENTER();
14116
14117 // Validate pAdapter
14118 if ( NULL == pAdapter )
14119 {
14120 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
14121 return -EINVAL;
14122 }
14123
14124 if (!pmksa) {
14125 hddLog(LOGE, FL("pmksa is NULL"));
14126 return -EINVAL;
14127 }
14128
14129 if (!pmksa->bssid || !pmksa->pmkid) {
14130 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
14131 pmksa->bssid, pmksa->pmkid);
14132 return -EINVAL;
14133 }
14134
14135 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: set PMKSA for " MAC_ADDRESS_STR,
14136 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
14137
14138 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14139 status = wlan_hdd_validate_context(pHddCtx);
14140 if (0 != status)
14141 {
14142 return status;
14143 }
14144
14145 // Retrieve halHandle
14146 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14147
14148 vos_mem_copy(pmk_id.BSSID, pmksa->bssid, ETHER_ADDR_LEN);
14149 vos_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
14150
14151 /* Add to the PMKSA ID Cache in CSR */
14152 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
14153 &pmk_id, 1, FALSE);
14154
14155 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
14156 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14157 pAdapter->sessionId, result));
14158
14159 EXIT();
14160 return HAL_STATUS_SUCCESS(result) ? 0 : -EINVAL;
14161}
14162
14163static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
14164 struct cfg80211_pmksa *pmksa)
14165{
14166 int ret;
14167
14168 vos_ssr_protect(__func__);
14169 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14170 vos_ssr_unprotect(__func__);
14171
14172 return ret;
14173}
14174
14175
14176static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
14177 struct cfg80211_pmksa *pmksa)
14178{
14179 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14180 tHalHandle halHandle;
14181 hdd_context_t *pHddCtx;
14182 int status = 0;
14183
14184 ENTER();
14185
14186 /* Validate pAdapter */
14187 if (NULL == pAdapter)
14188 {
14189 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
14190 return -EINVAL;
14191 }
14192
14193 if (!pmksa) {
14194 hddLog(LOGE, FL("pmksa is NULL"));
14195 return -EINVAL;
14196 }
14197
14198 if (!pmksa->bssid) {
14199 hddLog(LOGE, FL("pmksa->bssid is NULL"));
14200 return -EINVAL;
14201 }
14202
14203 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: deleting PMKSA for " MAC_ADDRESS_STR,
14204 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
14205
14206 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14207 status = wlan_hdd_validate_context(pHddCtx);
14208 if (0 != status)
14209 {
14210 return status;
14211 }
14212
14213 /*Retrieve halHandle*/
14214 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14215
14216 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
14217 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14218 pAdapter->sessionId, 0));
14219 /* Delete the PMKID CSR cache */
14220 if (eHAL_STATUS_SUCCESS !=
14221 sme_RoamDelPMKIDfromCache(halHandle,
14222 pAdapter->sessionId, pmksa->bssid, FALSE)) {
14223 hddLog(LOGE, FL("Failed to delete PMKSA for "MAC_ADDRESS_STR),
14224 MAC_ADDR_ARRAY(pmksa->bssid));
14225 status = -EINVAL;
14226 }
14227
14228 EXIT();
14229 return status;
14230}
14231
14232
14233static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
14234 struct cfg80211_pmksa *pmksa)
14235{
14236 int ret;
14237
14238 vos_ssr_protect(__func__);
14239 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14240 vos_ssr_unprotect(__func__);
14241
14242 return ret;
14243
14244}
14245
14246static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
14247{
14248 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14249 tHalHandle halHandle;
14250 hdd_context_t *pHddCtx;
14251 int status = 0;
14252
14253 ENTER();
14254
14255 /* Validate pAdapter */
14256 if (NULL == pAdapter)
14257 {
14258 hddLog(VOS_TRACE_LEVEL_ERROR,
14259 "%s: Invalid Adapter" ,__func__);
14260 return -EINVAL;
14261 }
14262
14263 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14264 status = wlan_hdd_validate_context(pHddCtx);
14265 if (0 != status)
14266 {
14267 return status;
14268 }
14269
14270 /*Retrieve halHandle*/
14271 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14272
14273 /* Flush the PMKID cache in CSR */
14274 if (eHAL_STATUS_SUCCESS !=
14275 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, NULL, TRUE)) {
14276 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Cannot flush PMKIDCache"));
14277 status = -EINVAL;
14278 }
14279 EXIT();
14280 return status;
14281}
14282
14283static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
14284{
14285 int ret;
14286
14287 vos_ssr_protect(__func__);
14288 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14289 vos_ssr_unprotect(__func__);
14290
14291 return ret;
14292}
14293#endif
14294
14295#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
14296static int __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14297 struct net_device *dev,
14298 struct cfg80211_update_ft_ies_params *ftie)
14299{
14300 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14301 hdd_station_ctx_t *pHddStaCtx;
14302 hdd_context_t *pHddCtx;
14303 int ret = 0;
14304
14305 ENTER();
14306
14307 if (NULL == pAdapter)
14308 {
14309 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
14310 return -ENODEV;
14311 }
14312 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14313 ret = wlan_hdd_validate_context(pHddCtx);
14314 if (0 != ret)
14315 {
14316 return ret;
14317 }
14318 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14319 if (NULL == pHddStaCtx)
14320 {
14321 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: STA Context is NULL", __func__);
14322 return -EINVAL;
14323 }
14324
14325 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
14326 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14327 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14328 // Added for debug on reception of Re-assoc Req.
14329 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
14330 {
14331 hddLog(LOGE, FL("Called with Ie of length = %zu when not associated"),
14332 ftie->ie_len);
14333 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
14334 }
14335
14336#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
14337 hddLog(LOGE, FL("%s called with Ie of length = %zu"), __func__,
14338 ftie->ie_len);
14339#endif
14340
14341 // Pass the received FT IEs to SME
14342 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14343 (const u8 *)ftie->ie,
14344 ftie->ie_len);
14345
14346 EXIT();
14347 return 0;
14348}
14349
14350static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14351 struct net_device *dev,
14352 struct cfg80211_update_ft_ies_params *ftie)
14353{
14354 int ret;
14355
14356 vos_ssr_protect(__func__);
14357 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14358 vos_ssr_unprotect(__func__);
14359
14360 return ret;
14361}
14362#endif
14363
14364#ifdef FEATURE_WLAN_SCAN_PNO
14365
14366void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
14367 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
14368{
14369 int ret;
14370 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
14371 hdd_context_t *pHddCtx;
14372
14373 ENTER();
14374
14375 if (NULL == pAdapter)
14376 {
14377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14378 "%s: HDD adapter is Null", __func__);
14379 return ;
14380 }
14381
14382 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14383 if (NULL == pHddCtx)
14384 {
14385 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14386 "%s: HDD context is Null!!!", __func__);
14387 return ;
14388 }
14389
14390 spin_lock(&pHddCtx->schedScan_lock);
14391 if (TRUE == pHddCtx->isWiphySuspended)
14392 {
14393 pHddCtx->isSchedScanUpdatePending = TRUE;
14394 spin_unlock(&pHddCtx->schedScan_lock);
14395 hddLog(VOS_TRACE_LEVEL_INFO,
14396 "%s: Update cfg80211 scan database after it resume", __func__);
14397 return ;
14398 }
14399 spin_unlock(&pHddCtx->schedScan_lock);
14400
14401 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
14402
14403 if (0 > ret)
14404 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
14405 else
14406 {
14407 /* Acquire wakelock to handle the case where APP's tries to suspend
14408 * immediatly after the driver gets connect request(i.e after pno)
14409 * from supplicant, this result in app's is suspending and not able
14410 * to process the connect request to AP */
14411 hdd_prevent_suspend_timeout(1000, WIFI_POWER_EVENT_WAKELOCK_SCAN);
14412 }
14413 cfg80211_sched_scan_results(pHddCtx->wiphy);
14414 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14415 "%s: cfg80211 scan result database updated", __func__);
14416}
14417
14418/*
14419 * FUNCTION: wlan_hdd_is_pno_allowed
14420 * Disallow pno if any session is active
14421 */
14422static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter)
14423{
14424 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14425 hdd_adapter_t *pTempAdapter = NULL;
14426 hdd_station_ctx_t *pStaCtx;
14427 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14428 int status = 0;
14429 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
14430
14431 /* The current firmware design does not allow PNO during any
14432 * active sessions. Hence, determine the active sessions
14433 * and return a failure.
14434 */
14435 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status))
14436 {
14437 pTempAdapter = pAdapterNode->pAdapter;
14438 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pTempAdapter);
14439
14440 if (((WLAN_HDD_INFRA_STATION == pTempAdapter->device_mode)
14441 && (eConnectionState_NotConnected != pStaCtx->conn_info.connState))
14442 || (WLAN_HDD_P2P_CLIENT == pTempAdapter->device_mode)
14443 || (WLAN_HDD_P2P_GO == pTempAdapter->device_mode)
14444 || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode)
14445 || (WLAN_HDD_TM_LEVEL_4 == pHddCtx->tmInfo.currentTmLevel)
14446 )
14447 {
14448 return eHAL_STATUS_FAILURE;
14449 }
14450 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14451 pAdapterNode = pNext;
14452 }
14453 return eHAL_STATUS_SUCCESS;
14454}
14455
14456void hdd_cfg80211_sched_scan_start_status_cb(void *callbackContext, VOS_STATUS status)
14457{
14458 hdd_adapter_t *pAdapter = callbackContext;
14459 hdd_context_t *pHddCtx;
14460
14461 ENTER();
14462
14463 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
14464 {
14465 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14466 FL("Invalid adapter or adapter has invalid magic"));
14467 return;
14468 }
14469
14470 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14471 if (0 != wlan_hdd_validate_context(pHddCtx))
14472 {
14473 return;
14474 }
14475
14476 if (VOS_STATUS_SUCCESS != status)
14477 {
14478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14479 FL("PNO enable response status = %d"), status);
14480 pHddCtx->isPnoEnable = FALSE;
14481 }
14482
14483 pAdapter->pno_req_status = (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY;
14484 complete(&pAdapter->pno_comp_var);
14485 EXIT();
14486}
14487
14488/*
14489 * FUNCTION: __wlan_hdd_cfg80211_sched_scan_start
14490 * Function to enable PNO
14491 */
14492static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
14493 struct net_device *dev, struct cfg80211_sched_scan_request *request)
14494{
14495 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14496 tSirPNOScanReq pnoRequest = {0};
14497 hdd_context_t *pHddCtx;
14498 tHalHandle hHal;
14499 v_U32_t i, indx, num_ch, tempInterval, j;
14500 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
14501 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
14502 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14503 eHalStatus status = eHAL_STATUS_FAILURE;
14504 int ret = 0;
14505 hdd_config_t *pConfig = NULL;
14506 v_U32_t num_ignore_dfs_ch = 0;
14507
14508 ENTER();
14509
14510 if (NULL == pAdapter)
14511 {
14512 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14513 "%s: HDD adapter is Null", __func__);
14514 return -ENODEV;
14515 }
14516
14517 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14518 ret = wlan_hdd_validate_context(pHddCtx);
14519
14520 if (0 != ret)
14521 {
14522 return -EINVAL;
14523 }
14524
14525 pConfig = pHddCtx->cfg_ini;
14526 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14527 if (NULL == hHal)
14528 {
14529 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14530 "%s: HAL context is Null!!!", __func__);
14531 return -EINVAL;
14532 }
14533 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
14534 TRACE_CODE_HDD_CFG80211_SCHED_SCAN_START,
14535 pAdapter->sessionId, pAdapter->device_mode));
14536 sme_ScanFlushResult(hHal, pAdapter->sessionId);
14537 ret = wlan_hdd_scan_abort(pAdapter);
14538 if (ret < 0)
14539 {
14540 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14541 "%s: aborting the existing scan is unsuccessfull", __func__);
14542 return -EBUSY;
14543 }
14544
14545 if (eHAL_STATUS_SUCCESS != wlan_hdd_is_pno_allowed(pAdapter))
14546 {
14547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
14548 FL("Cannot handle sched_scan"));
14549 return -EBUSY;
14550 }
14551
14552 if (TRUE == pHddCtx->isPnoEnable)
14553 {
14554 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
14555 FL("already PNO is enabled"));
14556 return -EBUSY;
14557 }
14558
14559 if (VOS_STATUS_SUCCESS != wlan_hdd_cancel_remain_on_channel(pHddCtx))
14560 {
14561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14562 "%s: abort ROC failed ", __func__);
14563 return -EBUSY;
14564 }
14565
14566 pHddCtx->isPnoEnable = TRUE;
14567
14568 pnoRequest.enable = 1; /*Enable PNO */
14569 pnoRequest.ucNetworksCount = request->n_match_sets;
14570
14571 if (( !pnoRequest.ucNetworksCount ) ||
14572 ( pnoRequest.ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
14573 {
14574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14575 "%s: Network input is not correct %d Max Network supported is %d",
14576 __func__, pnoRequest.ucNetworksCount,
14577 SIR_PNO_MAX_SUPP_NETWORKS);
14578 ret = -EINVAL;
14579 goto error;
14580 }
14581
14582 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
14583 {
14584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14585 "%s: Incorrect number of channels %d",
14586 __func__, request->n_channels);
14587 ret = -EINVAL;
14588 goto error;
14589 }
14590
14591 /* Framework provides one set of channels(all)
14592 * common for all saved profile */
14593 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14594 channels_allowed, &num_channels_allowed))
14595 {
14596 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14597 "%s: failed to get valid channel list", __func__);
14598 ret = -EINVAL;
14599 goto error;
14600 }
14601 /* Checking each channel against allowed channel list */
14602 num_ch = 0;
14603 if (request->n_channels)
14604 {
14605 char chList [(request->n_channels*5)+1];
14606 int len;
14607 for (i = 0, len = 0; i < request->n_channels; i++)
14608 {
14609 for (indx = 0; indx < num_channels_allowed; indx++)
14610 {
14611 if (request->channels[i]->hw_value == channels_allowed[indx])
14612 {
14613 if ((!pConfig->enableDFSPnoChnlScan) &&
14614 (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(channels_allowed[indx])))
14615 {
14616 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14617 "%s : Dropping DFS channel : %d",
14618 __func__,channels_allowed[indx]);
14619 num_ignore_dfs_ch++;
14620 break;
14621 }
14622
14623 valid_ch[num_ch++] = request->channels[i]->hw_value;
14624 len += snprintf(chList+len, 5, "%d ",
14625 request->channels[i]->hw_value);
14626 break ;
14627 }
14628 }
14629 }
14630 hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList);
14631
14632 /*If all channels are DFS and dropped, then ignore the PNO request*/
14633 if (num_ignore_dfs_ch == request->n_channels)
14634 {
14635 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14636 "%s : All requested channels are DFS channels", __func__);
14637 ret = -EINVAL;
14638 goto error;
14639 }
14640 }
14641
14642 pnoRequest.aNetworks =
14643 vos_mem_malloc(sizeof(tSirNetworkType)*pnoRequest.ucNetworksCount);
14644 if (pnoRequest.aNetworks == NULL)
14645 {
14646 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
14647 FL("failed to allocate memory aNetworks %u"),
14648 (uint32)sizeof(tSirNetworkType)*pnoRequest.ucNetworksCount);
14649 goto error;
14650 }
14651 vos_mem_zero(pnoRequest.aNetworks,
14652 sizeof(tSirNetworkType)*pnoRequest.ucNetworksCount);
14653
14654 /* Filling per profile params */
14655 for (i = 0; i < pnoRequest.ucNetworksCount; i++)
14656 {
14657 pnoRequest.aNetworks[i].ssId.length =
14658 request->match_sets[i].ssid.ssid_len;
14659
14660 if (( 0 == pnoRequest.aNetworks[i].ssId.length ) ||
14661 ( pnoRequest.aNetworks[i].ssId.length > 32 ) )
14662 {
14663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14664 "%s: SSID Len %d is not correct for network %d",
14665 __func__, pnoRequest.aNetworks[i].ssId.length, i);
14666 ret = -EINVAL;
14667 goto error;
14668 }
14669
14670 memcpy(pnoRequest.aNetworks[i].ssId.ssId,
14671 request->match_sets[i].ssid.ssid,
14672 request->match_sets[i].ssid.ssid_len);
14673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14674 "%s: SSID of network %d is %s ", __func__,
14675 i, pnoRequest.aNetworks[i].ssId.ssId);
14676 pnoRequest.aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
14677 pnoRequest.aNetworks[i].encryption = 0; /*eED_ANY*/
14678 pnoRequest.aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
14679
14680 /*Copying list of valid channel into request */
14681 memcpy(pnoRequest.aNetworks[i].aChannels, valid_ch, num_ch);
14682 pnoRequest.aNetworks[i].ucChannelCount = num_ch;
14683
14684 pnoRequest.aNetworks[i].rssiThreshold = 0; //Default value
14685 }
14686
14687 for (i = 0; i < request->n_ssids; i++)
14688 {
14689 j = 0;
14690 while (j < pnoRequest.ucNetworksCount)
14691 {
14692 if ((pnoRequest.aNetworks[j].ssId.length ==
14693 request->ssids[i].ssid_len) &&
14694 (0 == memcmp(pnoRequest.aNetworks[j].ssId.ssId,
14695 request->ssids[i].ssid,
14696 pnoRequest.aNetworks[j].ssId.length)))
14697 {
14698 pnoRequest.aNetworks[j].bcastNetwType = eBCAST_HIDDEN;
14699 break;
14700 }
14701 j++;
14702 }
14703 }
14704 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14705 "Number of hidden networks being Configured = %d",
14706 request->n_ssids);
14707 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14708 "request->ie_len = %zu", request->ie_len);
14709
14710 pnoRequest.p24GProbeTemplate = vos_mem_malloc(SIR_PNO_MAX_PB_REQ_SIZE);
14711 if (pnoRequest.p24GProbeTemplate == NULL)
14712 {
14713 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
14714 FL("failed to allocate memory p24GProbeTemplate %u"),
14715 SIR_PNO_MAX_PB_REQ_SIZE);
14716 goto error;
14717 }
14718
14719 pnoRequest.p5GProbeTemplate = vos_mem_malloc(SIR_PNO_MAX_PB_REQ_SIZE);
14720 if (pnoRequest.p5GProbeTemplate == NULL)
14721 {
14722 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
14723 FL("failed to allocate memory p5GProbeTemplate %u"),
14724 SIR_PNO_MAX_PB_REQ_SIZE);
14725 goto error;
14726 }
14727
14728 vos_mem_zero(pnoRequest.p24GProbeTemplate, SIR_PNO_MAX_PB_REQ_SIZE);
14729 vos_mem_zero(pnoRequest.p5GProbeTemplate, SIR_PNO_MAX_PB_REQ_SIZE);
14730
14731 if ((0 < request->ie_len) && (request->ie_len <= SIR_PNO_MAX_PB_REQ_SIZE) &&
14732 (NULL != request->ie))
14733 {
14734 pnoRequest.us24GProbeTemplateLen = request->ie_len;
14735 memcpy(pnoRequest.p24GProbeTemplate, request->ie,
14736 pnoRequest.us24GProbeTemplateLen);
14737
14738 pnoRequest.us5GProbeTemplateLen = request->ie_len;
14739 memcpy(pnoRequest.p5GProbeTemplate, request->ie,
14740 pnoRequest.us5GProbeTemplateLen);
14741 }
14742
14743 /* Driver gets only one time interval which is hardcoded in
14744 * supplicant for 10000ms. Taking power consumption into account 6 timers
14745 * will be used, Timervalue is increased exponentially i.e 10,20,40,
14746 * 80,160,320 secs. And number of scan cycle for each timer
14747 * is configurable through INI param gPNOScanTimerRepeatValue.
14748 * If it is set to 0 only one timer will be used and PNO scan cycle
14749 * will be repeated after each interval specified by supplicant
14750 * till PNO is disabled.
14751 */
14752 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
14753 pnoRequest.scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
14754 else
14755 pnoRequest.scanTimers.ucScanTimersCount =
14756 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
14757
14758 tempInterval = (request->interval)/1000;
14759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14760 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
14761 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
14762 for ( i = 0; i < pnoRequest.scanTimers.ucScanTimersCount; i++)
14763 {
14764 pnoRequest.scanTimers.aTimerValues[i].uTimerRepeat =
14765 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
14766 pnoRequest.scanTimers.aTimerValues[i].uTimerValue = tempInterval;
14767 tempInterval *= 2;
14768 }
14769 //Repeat last timer until pno disabled.
14770 pnoRequest.scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
14771
14772 pnoRequest.modePNO = SIR_PNO_MODE_IMMEDIATE;
14773
14774 INIT_COMPLETION(pAdapter->pno_comp_var);
14775 pnoRequest.statusCallback = hdd_cfg80211_sched_scan_start_status_cb;
14776 pnoRequest.callbackContext = pAdapter;
14777 pAdapter->pno_req_status = 0;
14778
14779 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14780 "SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d",
14781 pAdapter->sessionId, pnoRequest.enable, pnoRequest.modePNO,
14782 pnoRequest.scanTimers.ucScanTimersCount);
14783
14784 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
14785 &pnoRequest, pAdapter->sessionId,
14786 hdd_cfg80211_sched_scan_done_callback, pAdapter);
14787 if (eHAL_STATUS_SUCCESS != status)
14788 {
14789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14790 "%s: Failed to enable PNO", __func__);
14791 ret = -EINVAL;
14792 goto error;
14793 }
14794
14795 ret = wait_for_completion_timeout(
14796 &pAdapter->pno_comp_var,
14797 msecs_to_jiffies(WLAN_WAIT_TIME_PNO));
14798 if (0 >= ret)
14799 {
14800 // Did not receive the response for PNO enable in time.
14801 // Assuming the PNO enable was success.
14802 // Returning error from here, because we timeout, results
14803 // in side effect of Wifi (Wifi Setting) not to work.
14804 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14805 FL("Timed out waiting for PNO to be Enabled"));
14806 ret = 0;
14807 }
14808
14809 ret = pAdapter->pno_req_status;
14810 return ret;
14811
14812error:
14813 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14814 FL("PNO scanRequest offloaded ret = %d"), ret);
14815 pHddCtx->isPnoEnable = FALSE;
14816 if (pnoRequest.aNetworks)
14817 vos_mem_free(pnoRequest.aNetworks);
14818 if (pnoRequest.p24GProbeTemplate)
14819 vos_mem_free(pnoRequest.p24GProbeTemplate);
14820 if (pnoRequest.p5GProbeTemplate)
14821 vos_mem_free(pnoRequest.p5GProbeTemplate);
14822
14823 EXIT();
14824 return ret;
14825}
14826
14827/*
14828 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
14829 * NL interface to enable PNO
14830 */
14831static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
14832 struct net_device *dev, struct cfg80211_sched_scan_request *request)
14833{
14834 int ret;
14835
14836 vos_ssr_protect(__func__);
14837 ret = __wlan_hdd_cfg80211_sched_scan_start(wiphy, dev, request);
14838 vos_ssr_unprotect(__func__);
14839
14840 return ret;
14841}
14842
14843/*
14844 * FUNCTION: __wlan_hdd_cfg80211_sched_scan_stop
14845 * Function to disable PNO
14846 */
14847static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
14848 struct net_device *dev)
14849{
14850 eHalStatus status = eHAL_STATUS_FAILURE;
14851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14852 hdd_context_t *pHddCtx;
14853 tHalHandle hHal;
14854 tSirPNOScanReq pnoRequest = {0};
14855 int ret = 0;
14856
14857 ENTER();
14858
14859 if (NULL == pAdapter)
14860 {
14861 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14862 "%s: HDD adapter is Null", __func__);
14863 return -ENODEV;
14864 }
14865
14866 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14867
14868 if (NULL == pHddCtx)
14869 {
14870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14871 "%s: HDD context is Null", __func__);
14872 return -ENODEV;
14873 }
14874
14875 /* The return 0 is intentional when isLogpInProgress and
14876 * isLoadUnloadInProgress. We did observe a crash due to a return of
14877 * failure in sched_scan_stop , especially for a case where the unload
14878 * of the happens at the same time. The function __cfg80211_stop_sched_scan
14879 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
14880 * success. If it returns a failure , then its next invocation due to the
14881 * clean up of the second interface will have the dev pointer corresponding
14882 * to the first one leading to a crash.
14883 */
14884 if (pHddCtx->isLogpInProgress)
14885 {
14886 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14887 "%s: LOGP in Progress. Ignore!!!", __func__);
14888 pHddCtx->isPnoEnable = FALSE;
14889 return ret;
14890 }
14891
14892 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
14893 {
14894 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14895 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
14896 return ret;
14897 }
14898
14899 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14900 if (NULL == hHal)
14901 {
14902 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14903 "%s: HAL context is Null!!!", __func__);
14904 return -EINVAL;
14905 }
14906
14907 pnoRequest.enable = 0; /* Disable PNO */
14908 pnoRequest.ucNetworksCount = 0;
14909
14910 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
14911 TRACE_CODE_HDD_CFG80211_SCHED_SCAN_STOP,
14912 pAdapter->sessionId, pAdapter->device_mode));
14913
14914 INIT_COMPLETION(pAdapter->pno_comp_var);
14915 pnoRequest.statusCallback = hdd_cfg80211_sched_scan_start_status_cb;
14916 pnoRequest.callbackContext = pAdapter;
14917 pAdapter->pno_req_status = 0;
14918 status = sme_SetPreferredNetworkList(hHal, &pnoRequest,
14919 pAdapter->sessionId,
14920 NULL, pAdapter);
14921 if (eHAL_STATUS_SUCCESS != status)
14922 {
14923 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14924 "Failed to disabled PNO");
14925 ret = -EINVAL;
14926 goto error;
14927 }
14928 ret = wait_for_completion_timeout(
14929 &pAdapter->pno_comp_var,
14930 msecs_to_jiffies(WLAN_WAIT_TIME_PNO));
14931 if (0 >= ret)
14932 {
14933 // Did not receive the response for PNO disable in time.
14934 // Assuming the PNO disable was success.
14935 // Returning error from here, because we timeout, results
14936 // in side effect of Wifi (Wifi Setting) not to work.
14937 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14938 FL("Timed out waiting for PNO to be disabled"));
14939 ret = 0;
14940 }
14941
14942 ret = pAdapter->pno_req_status;
14943 pHddCtx->isPnoEnable = (ret == 0) ? FALSE : TRUE;
14944
14945error:
14946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14947 FL("PNO scan disabled ret = %d"), ret);
14948
14949 EXIT();
14950 return ret;
14951}
14952
14953/*
14954 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
14955 * NL interface to disable PNO
14956 */
14957static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
14958 struct net_device *dev)
14959{
14960 int ret;
14961
14962 vos_ssr_protect(__func__);
14963 ret = __wlan_hdd_cfg80211_sched_scan_stop(wiphy, dev);
14964 vos_ssr_unprotect(__func__);
14965
14966 return ret;
14967}
14968#endif /*FEATURE_WLAN_SCAN_PNO*/
14969
14970
14971#ifdef FEATURE_WLAN_TDLS
14972#if TDLS_MGMT_VERSION2
14973static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
14974 struct net_device *dev,
14975 u8 *peer, u8 action_code,
14976 u8 dialog_token,
14977 u16 status_code, u32 peer_capability,
14978 const u8 *buf, size_t len)
14979#else /* TDLS_MGMT_VERSION2 */
14980#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
14981static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
14982 struct net_device *dev,
14983 const u8 *peer, u8 action_code,
14984 u8 dialog_token, u16 status_code,
14985 u32 peer_capability, bool initiator,
14986 const u8 *buf, size_t len)
14987#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14988static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
14989 struct net_device *dev,
14990 const u8 *peer, u8 action_code,
14991 u8 dialog_token, u16 status_code,
14992 u32 peer_capability, const u8 *buf,
14993 size_t len)
14994#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14995static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
14996 struct net_device *dev,
14997 u8 *peer, u8 action_code,
14998 u8 dialog_token,
14999 u16 status_code, u32 peer_capability,
15000 const u8 *buf, size_t len)
15001#else
15002static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
15003 struct net_device *dev,
15004 u8 *peer, u8 action_code,
15005 u8 dialog_token,
15006 u16 status_code, const u8 *buf,
15007 size_t len)
15008#endif
15009#endif
15010{
15011 hdd_adapter_t *pAdapter;
15012 hdd_context_t *pHddCtx;
15013 VOS_STATUS status;
15014 int max_sta_failed = 0;
15015 int responder;
15016 long rc;
15017 int ret;
15018#if !(TDLS_MGMT_VERSION2) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0))
15019 u32 peer_capability = 0;
15020#endif
15021 tANI_U16 numCurrTdlsPeers;
15022 hdd_station_ctx_t *pHddStaCtx = NULL;
15023
15024 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15025 if (NULL == pAdapter)
15026 {
15027 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15028 "%s: Adapter is NULL",__func__);
15029 return -EINVAL;
15030 }
15031 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
15032 TRACE_CODE_HDD_CFG80211_TDLS_MGMT,
15033 pAdapter->sessionId, action_code));
15034
15035 pHddCtx = wiphy_priv(wiphy);
15036 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
15037 {
15038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15039 "Invalid arguments");
15040 return -EINVAL;
15041 }
15042
15043 if (pHddCtx->isLogpInProgress)
15044 {
15045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15046 "%s:LOGP in Progress. Ignore!!!", __func__);
15047 wlan_hdd_tdls_set_link_status(pAdapter,
15048 peer,
15049 eTDLS_LINK_IDLE,
15050 eTDLS_LINK_UNSPECIFIED);
15051 return -EBUSY;
15052 }
15053
15054 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
15055 {
15056 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15057 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
15058 return -EAGAIN;
15059 }
15060
15061 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
15062 {
15063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15064 "%s: TDLS mode is disabled OR not enabled in FW."
15065 MAC_ADDRESS_STR " action %d declined.",
15066 __func__, MAC_ADDR_ARRAY(peer), action_code);
15067 return -ENOTSUPP;
15068 }
15069
15070 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15071
15072 if( NULL == pHddStaCtx )
15073 {
15074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15075 "%s: HDD station context NULL ",__func__);
15076 return -EINVAL;
15077 }
15078
15079 /* STA should be connected and authenticated
15080 * before sending any TDLS frames
15081 */
15082 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
15083 (FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
15084 {
15085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15086 "STA is not connected or unauthenticated. "
15087 "connState %u, uIsAuthenticated %u",
15088 pHddStaCtx->conn_info.connState,
15089 pHddStaCtx->conn_info.uIsAuthenticated);
15090 return -EAGAIN;
15091 }
15092
15093 /* other than teardown frame, other mgmt frames are not sent if disabled */
15094 if (SIR_MAC_TDLS_TEARDOWN != action_code)
15095 {
15096 /* if tdls_mode is disabled to respond to peer's request */
15097 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
15098 {
15099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15100 "%s: " MAC_ADDRESS_STR
15101 " TDLS mode is disabled. action %d declined.",
15102 __func__, MAC_ADDR_ARRAY(peer), action_code);
15103
15104 return -ENOTSUPP;
15105 }
15106
15107 if (vos_max_concurrent_connections_reached())
15108 {
15109 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
15110 return -EINVAL;
15111 }
15112 }
15113
15114 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
15115 {
15116 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE))
15117 {
15118 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15119 "%s: " MAC_ADDRESS_STR
15120 " TDLS setup is ongoing. action %d declined.",
15121 __func__, MAC_ADDR_ARRAY(peer), action_code);
15122 return -EPERM;
15123 }
15124 }
15125
15126 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
15127 SIR_MAC_TDLS_SETUP_RSP == action_code )
15128 {
15129 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
15130 if (HDD_MAX_NUM_TDLS_STA <= numCurrTdlsPeers)
15131 {
15132 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
15133 we return error code at 'add_station()'. Hence we have this
15134 check again in addtion to add_station().
15135 Anyway, there is no hard to double-check. */
15136 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
15137 {
15138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15139 "%s: " MAC_ADDRESS_STR
15140 " TDLS Max peer already connected. action (%d) declined. Num of peers (%d), Max allowed (%d).",
15141 __func__, MAC_ADDR_ARRAY(peer), action_code,
15142 numCurrTdlsPeers, HDD_MAX_NUM_TDLS_STA);
15143 return -EINVAL;
15144 }
15145 else
15146 {
15147 /* maximum reached. tweak to send error code to peer and return
15148 error code to supplicant */
15149 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
15150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15151 "%s: " MAC_ADDRESS_STR
15152 " TDLS Max peer already connected, send response status (%d). Num of peers (%d), Max allowed (%d).",
15153 __func__, MAC_ADDR_ARRAY(peer), status_code,
15154 numCurrTdlsPeers, HDD_MAX_NUM_TDLS_STA);
15155 max_sta_failed = -EPERM;
15156 /* fall through to send setup resp with failure status
15157 code */
15158 }
15159 }
15160 else
15161 {
15162 hddTdlsPeer_t *pTdlsPeer;
15163 mutex_lock(&pHddCtx->tdls_lock);
15164 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
15165 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
15166 {
15167 mutex_unlock(&pHddCtx->tdls_lock);
15168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15169 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
15170 __func__, MAC_ADDR_ARRAY(peer), action_code);
15171 return -EPERM;
15172 }
15173 mutex_unlock(&pHddCtx->tdls_lock);
15174 }
15175 }
15176
15177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15178 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %zu",
15179 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
15180 action_code, dialog_token, status_code, len);
15181
15182 /*Except teardown responder will not be used so just make 0*/
15183 responder = 0;
15184 if (SIR_MAC_TDLS_TEARDOWN == action_code)
15185 {
15186
15187 hddTdlsPeer_t *pTdlsPeer;
15188
15189 mutex_lock(&pHddCtx->tdls_lock);
15190 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
15191
15192 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
15193 responder = pTdlsPeer->is_responder;
15194 else
15195 {
15196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15197 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %zu",
15198 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
15199 dialog_token, status_code, len);
15200 mutex_unlock(&pHddCtx->tdls_lock);
15201 return -EPERM;
15202 }
15203 mutex_unlock(&pHddCtx->tdls_lock);
15204 }
15205
15206 /* For explicit trigger of DIS_REQ come out of BMPS for
15207 successfully receiving DIS_RSP from peer. */
15208 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
15209 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
15210 (SIR_MAC_TDLS_DIS_REQ == action_code))
15211 {
15212 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
15213 {
15214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15215 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
15216 status = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
15217 if (status != VOS_STATUS_SUCCESS) {
15218 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set BMPS/IMPS"));
15219 }
15220 }
15221 if (SIR_MAC_TDLS_DIS_REQ != action_code) {
15222 if (0 != wlan_hdd_tdls_set_cap(pAdapter, peer, eTDLS_CAP_SUPPORTED)) {
15223 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set TDLS capabilities"));
15224 }
15225 }
15226 }
15227
15228 /* make sure doesn't call send_mgmt() while it is pending */
15229 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
15230 {
15231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15232 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY",
15233 __func__, MAC_ADDR_ARRAY(peer), action_code);
15234 ret = -EBUSY;
15235 goto tx_failed;
15236 }
15237
15238 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
15239 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
15240
15241 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
15242 pAdapter->sessionId, peer, action_code, dialog_token,
15243 status_code, peer_capability, (tANI_U8 *)buf, len,
15244 responder);
15245
15246 if (VOS_STATUS_SUCCESS != status)
15247 {
15248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15249 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
15250 pAdapter->mgmtTxCompletionStatus = FALSE;
15251 ret = -EINVAL;
15252 goto tx_failed;
15253 }
15254
15255 if ((SIR_MAC_TDLS_DIS_REQ == action_code) ||
15256 (SIR_MAC_TDLS_DIS_RSP == action_code))
15257 {
15258 /* for DIS_REQ/DIS_RSP, supplicant don't consider the return status.
15259 * So we no need to wait for tdls_mgmt_comp for sending ack status.
15260 */
15261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15262 "%s: tx done for frm %u", __func__, action_code);
15263 return 0;
15264 }
15265
15266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15267 "%s: Wait for tdls_mgmt_comp. Timeout %u ms", __func__,
15268 WAIT_TIME_TDLS_MGMT);
15269
15270 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
15271 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
15272
15273 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
15274 {
15275 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15276 "%s: Mgmt Tx Completion failed status %ld TxCompletion %u",
15277 __func__, rc, pAdapter->mgmtTxCompletionStatus);
15278 pAdapter->mgmtTxCompletionStatus = FALSE;
15279
15280 if (pHddCtx->isLogpInProgress)
15281 {
15282 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15283 "%s: LOGP in Progress. Ignore!!!", __func__);
15284 return -EAGAIN;
15285 }
15286
15287 ret = -EINVAL;
15288 goto tx_failed;
15289 }
15290 else
15291 {
15292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15293 "%s: Mgmt Tx Completion status %ld TxCompletion %u",
15294 __func__, rc, pAdapter->mgmtTxCompletionStatus);
15295 }
15296
15297 if (max_sta_failed)
15298 {
15299 ret = max_sta_failed;
15300 goto tx_failed;
15301 }
15302
15303 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
15304 {
15305 if (0 != wlan_hdd_tdls_set_responder(pAdapter, peer, TRUE)) {
15306 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set TDLS responder: Setup Response"));
15307 }
15308 }
15309 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
15310 {
15311 if (0 != wlan_hdd_tdls_set_responder(pAdapter, peer, FALSE)) {
15312 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set TDLS responder: Setup Response"));
15313 }
15314 }
15315
15316 return 0;
15317
15318tx_failed:
15319 /* add_station will be called before sending TDLS_SETUP_REQ and
15320 * TDLS_SETUP_RSP and as part of add_station driver will enable
15321 * BMPS. NL80211_TDLS_DISABLE_LINK will be called if the tx of
15322 * TDLS_SETUP_REQ or TDLS_SETUP_RSP fails. BMPS will be enabled
15323 * as part of processing NL80211_TDLS_DISABLE_LINK. So need to
15324 * enable BMPS for TDLS_SETUP_REQ and TDLS_SETUP_RSP if tx fails.
15325 */
15326
15327 if ((SIR_MAC_TDLS_SETUP_REQ == action_code) ||
15328 (SIR_MAC_TDLS_SETUP_RSP == action_code))
15329 wlan_hdd_tdls_check_bmps(pAdapter);
15330 return ret;
15331}
15332
15333#if TDLS_MGMT_VERSION2
15334static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
15335 u8 *peer, u8 action_code, u8 dialog_token,
15336 u16 status_code, u32 peer_capability,
15337 const u8 *buf, size_t len)
15338#else /* TDLS_MGMT_VERSION2 */
15339#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
15340static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
15341 struct net_device *dev,
15342 const u8 *peer, u8 action_code,
15343 u8 dialog_token, u16 status_code,
15344 u32 peer_capability, bool initiator,
15345 const u8 *buf, size_t len)
15346#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
15347static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
15348 struct net_device *dev,
15349 const u8 *peer, u8 action_code,
15350 u8 dialog_token, u16 status_code,
15351 u32 peer_capability, const u8 *buf,
15352 size_t len)
15353#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
15354static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
15355 struct net_device *dev,
15356 u8 *peer, u8 action_code,
15357 u8 dialog_token,
15358 u16 status_code, u32 peer_capability,
15359 const u8 *buf, size_t len)
15360#else
15361static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
15362 u8 *peer, u8 action_code, u8 dialog_token,
15363 u16 status_code, const u8 *buf, size_t len)
15364#endif
15365#endif
15366{
15367 int ret;
15368
15369 vos_ssr_protect(__func__);
15370#if TDLS_MGMT_VERSION2
15371 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
15372 dialog_token, status_code,
15373 peer_capability, buf, len);
15374#else /* TDLS_MGMT_VERSION2 */
15375#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
15376 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
15377 dialog_token, status_code,
15378 peer_capability, initiator,
15379 buf, len);
15380#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15381 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
15382 dialog_token, status_code,
15383 peer_capability, buf, len);
15384#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
15385 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
15386 dialog_token, status_code,
15387 peer_capability, buf, len);
15388#else
15389 ret = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
15390 dialog_token, status_code, buf, len);
15391#endif
15392#endif
15393 vos_ssr_unprotect(__func__);
15394
15395 return ret;
15396}
15397
15398int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter,
15399#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
15400 const u8 *peer,
15401#else
15402 u8 *peer,
15403#endif
15404 tdls_req_params_t *tdls_peer_params,
15405 cfg80211_exttdls_callback callback)
15406{
15407
15408 hddTdlsPeer_t *pTdlsPeer = NULL;
15409 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15410 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15411 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15412 " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
15413 __func__, MAC_ADDR_ARRAY(peer));
15414
15415 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
15416 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
15417
15418 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15419 " %s TDLS External control (%d) and Implicit Trigger (%d) not enabled ",
15420 __func__, pHddCtx->cfg_ini->fTDLSExternalControl,
15421 pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger);
15422 return -ENOTSUPP;
15423 }
15424
15425 /* To cater the requirement of establishing the TDLS link
15426 * irrespective of the data traffic , get an entry of TDLS peer.
15427 */
15428 mutex_lock(&pHddCtx->tdls_lock);
15429 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer);
15430 if (pTdlsPeer == NULL) {
15431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15432 "%s: peer " MAC_ADDRESS_STR " not existing",
15433 __func__, MAC_ADDR_ARRAY(peer));
15434 mutex_unlock(&pHddCtx->tdls_lock);
15435 return -EINVAL;
15436 }
15437
15438 /* check FW TDLS Off Channel capability */
15439 if ((TRUE == sme_IsFeatureSupportedByFW(TDLS_OFF_CHANNEL)) &&
15440 (TRUE == pHddCtx->cfg_ini->fEnableTDLSOffChannel) &&
15441 (NULL != tdls_peer_params))
15442 {
15443 pTdlsPeer->peerParams.channel = tdls_peer_params->channel;
15444 pTdlsPeer->peerParams.global_operating_class =
15445 tdls_peer_params->global_operating_class;
15446 pTdlsPeer->peerParams.max_latency_ms = tdls_peer_params->max_latency_ms;
15447 pTdlsPeer->peerParams.min_bandwidth_kbps =
15448 tdls_peer_params->min_bandwidth_kbps;
15449 /* check configured channel is valid, non dfs and
15450 * not current operating channel */
15451 if ((sme_IsTdlsOffChannelValid(WLAN_HDD_GET_HAL_CTX(pAdapter),
15452 tdls_peer_params->channel)) &&
15453 (pHddStaCtx) &&
15454 (tdls_peer_params->channel !=
15455 pHddStaCtx->conn_info.operationChannel))
15456 {
15457 pTdlsPeer->isOffChannelConfigured = TRUE;
15458 }
15459 else
15460 {
15461 pTdlsPeer->isOffChannelConfigured = FALSE;
15462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15463 "%s: Configured Tdls Off Channel is not valid", __func__);
15464
15465 }
15466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15467 "%s: tdls_off_channel %d isOffChannelConfigured %d "
15468 "current operating channel %d",
15469 __func__, pTdlsPeer->peerParams.channel,
15470 pTdlsPeer->isOffChannelConfigured,
15471 (pHddStaCtx ? pHddStaCtx->conn_info.operationChannel : 0));
15472 }
15473 else
15474 {
15475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15476 "%s: TDLS off channel FW capability %d, "
15477 "host capab %d or Invalid TDLS Peer Params", __func__,
15478 sme_IsFeatureSupportedByFW(TDLS_OFF_CHANNEL),
15479 pHddCtx->cfg_ini->fEnableTDLSOffChannel);
15480 }
15481
15482 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
15483
15484 mutex_unlock(&pHddCtx->tdls_lock);
15485
15486 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15487 " %s TDLS Add Force Peer Failed",
15488 __func__);
15489 return -EINVAL;
15490 }
15491 /*EXT TDLS*/
15492
15493 if ( 0 != wlan_hdd_set_callback(pTdlsPeer, callback) ) {
15494 mutex_unlock(&pHddCtx->tdls_lock);
15495 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15496 " %s TDLS set callback Failed",
15497 __func__);
15498 return -EINVAL;
15499 }
15500
15501 mutex_unlock(&pHddCtx->tdls_lock);
15502
15503 return(0);
15504
15505}
15506
15507int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter,
15508#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
15509 const u8 *peer
15510#else
15511 u8 *peer
15512#endif
15513)
15514{
15515
15516 hddTdlsPeer_t *pTdlsPeer;
15517 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15518 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15519 " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR,
15520 __func__, MAC_ADDR_ARRAY(peer));
15521
15522 if (0 != wlan_hdd_validate_context(pHddCtx)) {
15523 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is NULL"));
15524 return -EINVAL;
15525 }
15526
15527 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
15528 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
15529
15530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15531 " %s TDLS External control (%d) and Implicit Trigger (%d) not enabled ",
15532 __func__, pHddCtx->cfg_ini->fTDLSExternalControl,
15533 pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger);
15534 return -ENOTSUPP;
15535 }
15536
15537 mutex_lock(&pHddCtx->tdls_lock);
15538 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
15539
15540 if ( NULL == pTdlsPeer ) {
15541 mutex_unlock(&pHddCtx->tdls_lock);
15542 hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR
15543 " peer not existing",
15544 __func__, MAC_ADDR_ARRAY(peer));
15545 return -EINVAL;
15546 }
15547 else {
15548 wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
15549 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
15550 /* if channel switch is configured, reset
15551 the channel for this peer */
15552 if (TRUE == pTdlsPeer->isOffChannelConfigured)
15553 {
15554 pTdlsPeer->peerParams.channel = 0;
15555 pTdlsPeer->isOffChannelConfigured = FALSE;
15556 }
15557 }
15558
15559 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) ) {
15560 mutex_unlock(&pHddCtx->tdls_lock);
15561 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to set force peer"));
15562 return -EINVAL;
15563 }
15564
15565 /*EXT TDLS*/
15566
15567 if ( 0 != wlan_hdd_set_callback(pTdlsPeer, NULL )) {
15568 mutex_unlock(&pHddCtx->tdls_lock);
15569 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15570 " %s TDLS set callback Failed",
15571 __func__);
15572 return -EINVAL;
15573 }
15574
15575 mutex_unlock(&pHddCtx->tdls_lock);
15576
15577 return(0);
15578}
15579static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
15580#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
15581 const u8 *peer,
15582#else
15583 u8 *peer,
15584#endif
15585 enum nl80211_tdls_operation oper)
15586{
15587 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15588 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15589 int status;
15590 hddTdlsPeer_t *pTdlsPeer;
15591
15592 ENTER();
15593
15594 if (!pAdapter) {
15595 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adpater is NULL"));
15596 return -EINVAL;
15597 }
15598
15599 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
15600 TRACE_CODE_HDD_CFG80211_TDLS_OPER,
15601 pAdapter->sessionId, oper));
15602 if ( NULL == peer )
15603 {
15604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15605 "%s: Invalid arguments", __func__);
15606 return -EINVAL;
15607 }
15608
15609 status = wlan_hdd_validate_context(pHddCtx);
15610 if (0 != status)
15611 {
15612 return status;
15613 }
15614
15615
15616 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
15617 FALSE == sme_IsFeatureSupportedByFW(TDLS))
15618 {
15619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15620 "TDLS Disabled in INI (%d) OR not enabled in FW (%d) "
15621 "Cannot process TDLS commands",
15622 pHddCtx->cfg_ini->fEnableTDLSSupport,
15623 sme_IsFeatureSupportedByFW(TDLS));
15624 return -ENOTSUPP;
15625 }
15626
15627 switch (oper) {
15628 case NL80211_TDLS_ENABLE_LINK:
15629 {
15630 VOS_STATUS status;
15631 long ret;
15632 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
15633 WLAN_STADescType staDesc;
15634 tANI_U16 numCurrTdlsPeers = 0;
15635 hddTdlsPeer_t *connPeer = NULL;
15636 tANI_U8 suppChannelLen = 0;
15637
15638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15639 " %s : NL80211_TDLS_ENABLE_LINK for " MAC_ADDRESS_STR,
15640 __func__, MAC_ADDR_ARRAY(peer));
15641
15642 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
15643 memset(&staDesc, 0, sizeof(staDesc));
15644 if ( NULL == pTdlsPeer ) {
15645 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
15646 " (oper %d) not exsting. ignored",
15647 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
15648 return -EINVAL;
15649 }
15650
15651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15652 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
15653 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
15654 "NL80211_TDLS_ENABLE_LINK");
15655
15656 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
15657 {
15658 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
15659 MAC_ADDRESS_STR " failed",
15660 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
15661 return -EINVAL;
15662 }
15663
15664 /* before starting tdls connection, set tdls
15665 * off channel established status to default value */
15666 pTdlsPeer->isOffChannelEstablished = FALSE;
15667 /* TDLS Off Channel, Disable tdls channel switch,
15668 when there are more than one tdls link */
15669 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
15670 if (numCurrTdlsPeers == 2)
15671 {
15672 /* get connected peer and send disable tdls off chan */
15673 connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
15674 if ((connPeer) &&
15675 (connPeer->isOffChannelSupported == TRUE) &&
15676 (connPeer->isOffChannelConfigured == TRUE))
15677 {
15678 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15679 "%s: More then one peer connected, Disable "
15680 "TDLS channel switch", __func__);
15681
15682 connPeer->isOffChannelEstablished = FALSE;
15683
15684 ret = sme_SendTdlsChanSwitchReq(
15685 WLAN_HDD_GET_HAL_CTX(pAdapter),
15686 pAdapter->sessionId,
15687 connPeer->peerMac,
15688 connPeer->peerParams.channel,
15689 TDLS_OFF_CHANNEL_BW_OFFSET,
15690 TDLS_CHANNEL_SWITCH_DISABLE);
15691 if (ret != VOS_STATUS_SUCCESS) {
15692 hddLog(VOS_TRACE_LEVEL_ERROR,
15693 FL("Failed to send TDLS switch channel request"));
15694 }
15695 }
15696 else
15697 {
15698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15699 "%s: No TDLS Connected Peer or "
15700 "isOffChannelSupported %d "
15701 "isOffChannelConfigured %d",
15702 __func__,
15703 (connPeer ? (connPeer->isOffChannelSupported)
15704 : -1),
15705 (connPeer ? (connPeer->isOffChannelConfigured)
15706 : -1));
15707 }
15708 }
15709
15710 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
15711 {
15712 if (IS_ADVANCE_TDLS_ENABLE) {
15713
15714 if (0 != wlan_hdd_tdls_get_link_establish_params(
15715 pAdapter, peer,&tdlsLinkEstablishParams)) {
15716 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to get link establishment params"));
15717 return -EINVAL;
15718 }
15719 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
15720
15721 ret = sme_SendTdlsLinkEstablishParams(
15722 WLAN_HDD_GET_HAL_CTX(pAdapter),
15723 pAdapter->sessionId, peer,
15724 &tdlsLinkEstablishParams);
15725 if (ret != VOS_STATUS_SUCCESS) {
15726 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to send link establishment params"));
15727 }
15728 /* Send TDLS peer UAPSD capabilities to the firmware and
15729 * register with the TL on after the response for this operation
15730 * is received .
15731 */
15732 ret = wait_for_completion_interruptible_timeout(
15733 &pAdapter->tdls_link_establish_req_comp,
15734 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
15735 if (ret <= 0)
15736 {
15737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15738 FL("Link Establish Request Failed Status %ld"),
15739 ret);
15740 return -EINVAL;
15741 }
15742 }
15743
15744 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer,
15745 eTDLS_LINK_CONNECTED,
15746 eTDLS_LINK_SUCCESS);
15747 staDesc.ucSTAId = pTdlsPeer->staId;
15748 staDesc.ucQosEnabled = tdlsLinkEstablishParams.qos;
15749 ret = WLANTL_UpdateTdlsSTAClient(
15750 pHddCtx->pvosContext,
15751 &staDesc);
15752 if (ret != VOS_STATUS_SUCCESS) {
15753 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to update TDLS STA params"));
15754 }
15755
15756 /* Mark TDLS client Authenticated .*/
15757 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
15758 pTdlsPeer->staId,
15759 WLANTL_STA_AUTHENTICATED);
15760 if (VOS_STATUS_SUCCESS == status)
15761 {
15762 if (pTdlsPeer->is_responder == 0)
15763 {
15764 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
15765 tdlsConnInfo_t *tdlsInfo;
15766
15767 tdlsInfo = wlan_hdd_get_conn_info(pHddCtx, staId);
15768
15769 /* Initialize initiator wait callback */
15770 vos_timer_init(
15771 &pTdlsPeer->initiatorWaitTimeoutTimer,
15772 VOS_TIMER_TYPE_SW,
15773 wlan_hdd_tdls_initiator_wait_cb,
15774 tdlsInfo);
15775
15776 wlan_hdd_tdls_timer_restart(pAdapter,
15777 &pTdlsPeer->initiatorWaitTimeoutTimer,
15778 WAIT_TIME_TDLS_INITIATOR);
15779 /* suspend initiator TX until it receives direct packet from the
15780 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
15781 ret = WLANTL_SuspendDataTx(
15782 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
15783 &staId, NULL);
15784 if (ret != VOS_STATUS_SUCCESS) {
15785 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to suspend data tx"));
15786 }
15787 }
15788
15789 if ((TRUE == pTdlsPeer->isOffChannelSupported) &&
15790 (TRUE == pTdlsPeer->isOffChannelConfigured))
15791 {
15792 suppChannelLen =
15793 tdlsLinkEstablishParams.supportedChannelsLen;
15794
15795 if ((suppChannelLen > 0) &&
15796 (suppChannelLen <= SIR_MAC_MAX_SUPP_CHANNELS))
15797 {
15798 tANI_U8 suppPeerChannel = 0;
15799 int i = 0;
15800 for (i = 0U; i < suppChannelLen; i++)
15801 {
15802 suppPeerChannel =
15803 tdlsLinkEstablishParams.supportedChannels[i];
15804
15805 pTdlsPeer->isOffChannelSupported = FALSE;
15806 if (suppPeerChannel ==
15807 pTdlsPeer->peerParams.channel)
15808 {
15809 pTdlsPeer->isOffChannelSupported = TRUE;
15810 break;
15811 }
15812 }
15813 }
15814 else
15815 {
15816 pTdlsPeer->isOffChannelSupported = FALSE;
15817 }
15818 }
15819 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15820 "%s: TDLS channel switch request for channel "
15821 "%d isOffChannelConfigured %d suppChannelLen "
15822 "%d isOffChannelSupported %d", __func__,
15823 pTdlsPeer->peerParams.channel,
15824 pTdlsPeer->isOffChannelConfigured,
15825 suppChannelLen,
15826 pTdlsPeer->isOffChannelSupported);
15827
15828 /* TDLS Off Channel, Enable tdls channel switch,
15829 when their is only one tdls link and it supports */
15830 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
15831 if ((numCurrTdlsPeers == 1) &&
15832 (TRUE == pTdlsPeer->isOffChannelSupported) &&
15833 (TRUE == pTdlsPeer->isOffChannelConfigured))
15834 {
15835 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15836 "%s: Send TDLS channel switch request for channel %d",
15837 __func__, pTdlsPeer->peerParams.channel);
15838
15839 pTdlsPeer->isOffChannelEstablished = TRUE;
15840 ret = sme_SendTdlsChanSwitchReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
15841 pAdapter->sessionId,
15842 pTdlsPeer->peerMac,
15843 pTdlsPeer->peerParams.channel,
15844 TDLS_OFF_CHANNEL_BW_OFFSET,
15845 TDLS_CHANNEL_SWITCH_ENABLE);
15846 if (ret != VOS_STATUS_SUCCESS) {
15847 hddLog(VOS_TRACE_LEVEL_ERROR, FL("TDLS offchannel: Failed to send TDLS switch channel req"));
15848 }
15849 }
15850 else
15851 {
15852 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15853 "%s: TDLS channel switch request not sent"
15854 " numCurrTdlsPeers %d "
15855 "isOffChannelSupported %d "
15856 "isOffChannelConfigured %d",
15857 __func__, numCurrTdlsPeers,
15858 pTdlsPeer->isOffChannelSupported,
15859 pTdlsPeer->isOffChannelConfigured);
15860 }
15861
15862 }
15863 wlan_hdd_tdls_check_bmps(pAdapter);
15864
15865 /* Update TL about the UAPSD masks , to route the packets to firmware */
15866 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
15867 || pHddCtx->cfg_ini->fTDLSUapsdMask )
15868 {
15869 int ac;
15870 uint8 ucAc[4] = { WLANTL_AC_VO,
15871 WLANTL_AC_VI,
15872 WLANTL_AC_BK,
15873 WLANTL_AC_BE };
15874 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
15875 for(ac=0; ac < 4; ac++)
15876 {
15877 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
15878 pTdlsPeer->staId, ucAc[ac],
15879 tlTid[ac], tlTid[ac], 0, 0,
15880 WLANTL_BI_DIR );
15881 if (status != VOS_STATUS_SUCCESS) {
15882 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to enable UAPSD for AC"));
15883 }
15884 }
15885 }
15886 }
15887 }
15888 break;
15889 case NL80211_TDLS_DISABLE_LINK:
15890 {
15891 tANI_U16 numCurrTdlsPeers = 0;
15892 hddTdlsPeer_t *connPeer = NULL;
15893
15894 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15895 " %s : NL80211_TDLS_DISABLE_LINK for " MAC_ADDRESS_STR,
15896 __func__, MAC_ADDR_ARRAY(peer));
15897
15898 mutex_lock(&pHddCtx->tdls_lock);
15899 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
15900
15901
15902 if ( NULL == pTdlsPeer ) {
15903 mutex_unlock(&pHddCtx->tdls_lock);
15904 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
15905 " (oper %d) not exsting. ignored",
15906 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
15907 return -EINVAL;
15908 }
15909
15910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15911 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
15912 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
15913 "NL80211_TDLS_DISABLE_LINK");
15914
15915 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
15916 {
15917 long status;
15918
15919 /* set tdls off channel status to false for this peer */
15920 pTdlsPeer->isOffChannelEstablished = FALSE;
15921 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer,
15922 eTDLS_LINK_TEARING,
15923 (pTdlsPeer->link_status == eTDLS_LINK_TEARING)?
15924 eTDLS_LINK_UNSPECIFIED:
15925 eTDLS_LINK_DROPPED_BY_REMOTE);
15926 mutex_unlock(&pHddCtx->tdls_lock);
15927
15928 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
15929
15930 status = sme_DeleteTdlsPeerSta(
15931 WLAN_HDD_GET_HAL_CTX(pAdapter),
15932 pAdapter->sessionId, peer );
15933 if (status != VOS_STATUS_SUCCESS) {
15934 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to delete TDLS peer STA"));
15935 }
15936
15937 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
15938 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
15939
15940 mutex_lock(&pHddCtx->tdls_lock);
15941 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, FALSE);
15942 if ( NULL == pTdlsPeer ) {
15943 mutex_unlock(&pHddCtx->tdls_lock);
15944 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
15945 " peer was freed in other context",
15946 __func__, MAC_ADDR_ARRAY(peer));
15947 return -EINVAL;
15948 }
15949
15950 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer,
15951 eTDLS_LINK_IDLE,
15952 eTDLS_LINK_UNSPECIFIED);
15953 mutex_unlock(&pHddCtx->tdls_lock);
15954
15955 if (status <= 0)
15956 {
15957 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15958 "%s: Del station failed status %ld",
15959 __func__, status);
15960 return -EPERM;
15961 }
15962
15963 /* TDLS Off Channel, Enable tdls channel switch,
15964 when their is only one tdls link and it supports */
15965 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
15966 if (numCurrTdlsPeers == 1)
15967 {
15968 tSirMacAddr peerMac;
15969 int channel;
15970
15971 mutex_lock(&pHddCtx->tdls_lock);
15972 connPeer = wlan_hdd_tdls_get_connected_peer(pAdapter);
15973
15974 if (connPeer == NULL) {
15975 mutex_unlock(&pHddCtx->tdls_lock);
15976 hddLog(VOS_TRACE_LEVEL_ERROR,
15977 "%s connPeer is NULL", __func__);
15978 return -EINVAL;
15979 }
15980
15981 vos_mem_copy(peerMac, connPeer->peerMac, sizeof(tSirMacAddr));
15982 channel = connPeer->peerParams.channel;
15983
15984 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15985 "%s: TDLS channel switch "
15986 "isOffChannelSupported %d "
15987 "isOffChannelConfigured %d "
15988 "isOffChannelEstablished %d",
15989 __func__,
15990 (connPeer ? connPeer->isOffChannelSupported : -1),
15991 (connPeer ? connPeer->isOffChannelConfigured : -1),
15992 (connPeer ? connPeer->isOffChannelEstablished : -1));
15993
15994 if ((connPeer) &&
15995 (connPeer->isOffChannelSupported == TRUE) &&
15996 (connPeer->isOffChannelConfigured == TRUE))
15997 {
15998 connPeer->isOffChannelEstablished = TRUE;
15999 mutex_unlock(&pHddCtx->tdls_lock);
16000 status = sme_SendTdlsChanSwitchReq(
16001 WLAN_HDD_GET_HAL_CTX(pAdapter),
16002 pAdapter->sessionId,
16003 peerMac,
16004 channel,
16005 TDLS_OFF_CHANNEL_BW_OFFSET,
16006 TDLS_CHANNEL_SWITCH_ENABLE);
16007 if (status != VOS_STATUS_SUCCESS) {
16008 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to send TDLS switch channel req"));
16009 }
16010 }
16011 else
16012 mutex_unlock(&pHddCtx->tdls_lock);
16013 }
16014 else
16015 {
16016 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16017 "%s: TDLS channel switch request not sent "
16018 "numCurrTdlsPeers %d ",
16019 __func__, numCurrTdlsPeers);
16020 }
16021 }
16022 else
16023 {
16024 mutex_unlock(&pHddCtx->tdls_lock);
16025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16026 "%s: TDLS Peer Station doesn't exist.", __func__);
16027 }
16028 }
16029 break;
16030 case NL80211_TDLS_TEARDOWN:
16031 {
16032 status = wlan_hdd_tdls_extctrl_deconfig_peer(pAdapter, peer);
16033
16034 if (0 != status)
16035 {
16036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16037 FL("Error in TDLS Teardown"));
16038 return status;
16039 }
16040 break;
16041 }
16042 case NL80211_TDLS_SETUP:
16043 {
16044 status = wlan_hdd_tdls_extctrl_config_peer(pAdapter,
16045 peer,
16046 NULL,
16047 NULL);
16048
16049 if (0 != status)
16050 {
16051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16052 FL("Error in TDLS Setup"));
16053 return status;
16054 }
16055 break;
16056 }
16057 case NL80211_TDLS_DISCOVERY_REQ:
16058 /* We don't support in-driver setup/teardown/discovery */
16059 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
16060 "%s: Driver doesn't support in-driver setup/teardown/discovery "
16061 ,__func__);
16062 return -ENOTSUPP;
16063 default:
16064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16065 "%s: unsupported event",__func__);
16066 return -ENOTSUPP;
16067 }
16068
16069 EXIT();
16070 return 0;
16071}
16072
16073static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
16074#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
16075 const u8 *peer,
16076#else
16077 u8 *peer,
16078#endif
16079 enum nl80211_tdls_operation oper)
16080{
16081 int ret;
16082
16083 vos_ssr_protect(__func__);
16084 ret = __wlan_hdd_cfg80211_tdls_oper(wiphy, dev, peer, oper);
16085 vos_ssr_unprotect(__func__);
16086
16087 return ret;
16088}
16089
16090int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
16091 struct net_device *dev, u8 *peer)
16092{
16093 hddLog(VOS_TRACE_LEVEL_INFO,
16094 "tdls send discover req: "MAC_ADDRESS_STR,
16095 MAC_ADDR_ARRAY(peer));
16096
16097#if TDLS_MGMT_VERSION2
16098 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
16099 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0);
16100#else
16101#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
16102 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
16103 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, 0, NULL, 0);
16104#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
16105 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
16106 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0);
16107#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
16108 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
16109 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0);
16110#else
16111 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
16112 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
16113#endif
16114#endif /* KERNEL_VERSION */
16115}
16116#endif
16117
16118#ifdef WLAN_FEATURE_GTK_OFFLOAD
16119/*
16120 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
16121 * Callback rountine called upon receiving response for
16122 * get offload info
16123 */
16124void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
16125 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
16126{
16127
16128 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
16129 tANI_U8 tempReplayCounter[8];
16130 hdd_station_ctx_t *pHddStaCtx;
16131
16132 ENTER();
16133
16134 if (NULL == pAdapter)
16135 {
16136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16137 "%s: HDD adapter is Null", __func__);
16138 return ;
16139 }
16140
16141 if (NULL == pGtkOffloadGetInfoRsp)
16142 {
16143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16144 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
16145 return ;
16146 }
16147
16148 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
16149 {
16150 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16151 "%s: wlan Failed to get replay counter value",
16152 __func__);
16153 return ;
16154 }
16155
16156 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16157 /* Update replay counter */
16158 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
16159 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
16160
16161 {
16162 /* changing from little to big endian since supplicant
16163 * works on big endian format
16164 */
16165 int i;
16166 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
16167
16168 for (i = 0; i < 8; i++)
16169 {
16170 tempReplayCounter[7-i] = (tANI_U8)p[i];
16171 }
16172 }
16173
16174 /* Update replay counter to NL */
16175 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
16176 tempReplayCounter, GFP_KERNEL);
16177}
16178
16179/*
16180 * FUNCTION: __wlan_hdd_cfg80211_set_rekey_data
16181 * This function is used to offload GTK rekeying job to the firmware.
16182 */
16183int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
16184 struct cfg80211_gtk_rekey_data *data)
16185{
16186 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16187 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16188 hdd_station_ctx_t *pHddStaCtx;
16189 tHalHandle hHal;
16190 int result;
16191 tSirGtkOffloadParams hddGtkOffloadReqParams;
16192 eHalStatus status = eHAL_STATUS_FAILURE;
16193
16194 ENTER();
16195
16196 if (NULL == pAdapter)
16197 {
16198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
16199 "%s: HDD adapter is Null", __func__);
16200 return -ENODEV;
16201 }
16202
16203 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
16204 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16205 pAdapter->sessionId, pAdapter->device_mode));
16206
16207 result = wlan_hdd_validate_context(pHddCtx);
16208 if (0 != result)
16209 {
16210 return result;
16211 }
16212
16213 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16214 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
16215 if (NULL == hHal)
16216 {
16217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16218 "%s: HAL context is Null!!!", __func__);
16219 return -EAGAIN;
16220 }
16221
16222 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
16223 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
16224 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
16225 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
16226 WNI_CFG_BSSID_LEN);
16227 {
16228 /* changing from big to little endian since driver
16229 * works on little endian format
16230 */
16231 tANI_U8 *p =
16232 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
16233 int i;
16234
16235 for (i = 0; i < 8; i++)
16236 {
16237 p[7-i] = data->replay_ctr[i];
16238 }
16239 }
16240
16241 if (TRUE == pHddCtx->hdd_wlan_suspended)
16242 {
16243 /* if wlan is suspended, enable GTK offload directly from here */
16244 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
16245 sizeof (tSirGtkOffloadParams));
16246 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
16247 pAdapter->sessionId);
16248
16249 if (eHAL_STATUS_SUCCESS != status)
16250 {
16251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16252 "%s: sme_SetGTKOffload failed, returned %d",
16253 __func__, status);
16254
16255 /* Need to clear any trace of key value in the memory.
16256 * Thus zero out the memory even though it is local
16257 * variable.
16258 */
16259 vos_mem_zero(&hddGtkOffloadReqParams,
16260 sizeof(hddGtkOffloadReqParams));
16261 return status;
16262 }
16263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16264 "%s: sme_SetGTKOffload successfull", __func__);
16265 }
16266 else
16267 {
16268 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16269 "%s: wlan not suspended GTKOffload request is stored",
16270 __func__);
16271 }
16272
16273 /* Need to clear any trace of key value in the memory.
16274 * Thus zero out the memory even though it is local
16275 * variable.
16276 */
16277 vos_mem_zero(&hddGtkOffloadReqParams,
16278 sizeof(hddGtkOffloadReqParams));
16279
16280 EXIT();
16281 return eHAL_STATUS_SUCCESS;
16282}
16283
16284int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
16285 struct cfg80211_gtk_rekey_data *data)
16286{
16287 int ret;
16288
16289 vos_ssr_protect(__func__);
16290 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16291 vos_ssr_unprotect(__func__);
16292
16293 return ret;
16294}
16295#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
16296/*
16297 * FUNCTION: __wlan_hdd_cfg80211_set_mac_acl
16298 * This function is used to set access control policy
16299 */
16300static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16301 struct net_device *dev,
16302 const struct cfg80211_acl_data *params)
16303{
16304 int i;
16305 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16306 hdd_hostapd_state_t *pHostapdState;
16307 tsap_Config_t *pConfig;
16308 v_CONTEXT_t pVosContext = NULL;
16309 hdd_context_t *pHddCtx;
16310 int status;
16311
16312 ENTER();
16313
16314 if (NULL == pAdapter)
16315 {
16316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
16317 "%s: HDD adapter is Null", __func__);
16318 return -ENODEV;
16319 }
16320
16321 if (NULL == params)
16322 {
16323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
16324 "%s: params is Null", __func__);
16325 return -EINVAL;
16326 }
16327
16328 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16329 status = wlan_hdd_validate_context(pHddCtx);
16330 if (0 != status)
16331 {
16332 return status;
16333 }
16334
16335 pVosContext = pHddCtx->pvosContext;
16336 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16337
16338 if (NULL == pHostapdState)
16339 {
16340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
16341 "%s: pHostapdState is Null", __func__);
16342 return -EINVAL;
16343 }
16344
16345 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
16346 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
16347 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
16348 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16349 pAdapter->sessionId, pAdapter->device_mode));
16350
16351 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
16352 {
16353 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16354
16355 /* default value */
16356 pConfig->num_accept_mac = 0;
16357 pConfig->num_deny_mac = 0;
16358
16359 /**
16360 * access control policy
16361 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16362 * listed in hostapd.deny file.
16363 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16364 * listed in hostapd.accept file.
16365 */
16366 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
16367 {
16368 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16369 }
16370 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
16371 {
16372 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16373 }
16374 else
16375 {
16376 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16377 "%s:Acl Policy : %d is not supported",
16378 __func__, params->acl_policy);
16379 return -ENOTSUPP;
16380 }
16381
16382 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
16383 {
16384 pConfig->num_accept_mac = params->n_acl_entries;
16385 for (i = 0; i < params->n_acl_entries; i++)
16386 {
16387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16388 "** Add ACL MAC entry %i in WhiletList :"
16389 MAC_ADDRESS_STR, i,
16390 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
16391
16392 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
16393 sizeof(qcmacaddr));
16394 }
16395 }
16396 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
16397 {
16398 pConfig->num_deny_mac = params->n_acl_entries;
16399 for (i = 0; i < params->n_acl_entries; i++)
16400 {
16401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16402 "** Add ACL MAC entry %i in BlackList :"
16403 MAC_ADDRESS_STR, i,
16404 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
16405
16406 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
16407 sizeof(qcmacaddr));
16408 }
16409 }
16410
16411 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
16412 {
16413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16414 "%s: SAP Set Mac Acl fail", __func__);
16415 return -EINVAL;
16416 }
16417 }
16418 else
16419 {
16420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16421 "%s: Invalid device_mode = %s (%d)",
16422 __func__, hdd_device_modetoString(pAdapter->device_mode),
16423 pAdapter->device_mode);
16424 return -EINVAL;
16425 }
16426
16427 EXIT();
16428 return 0;
16429}
16430
16431static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16432 struct net_device *dev,
16433 const struct cfg80211_acl_data *params)
16434{
16435 int ret;
16436 vos_ssr_protect(__func__);
16437 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16438 vos_ssr_unprotect(__func__);
16439
16440 return ret;
16441}
16442
16443#ifdef WLAN_NL80211_TESTMODE
16444#ifdef FEATURE_WLAN_LPHB
16445void wlan_hdd_cfg80211_lphb_ind_handler
16446(
16447 void *pAdapter,
16448 void *indCont
16449)
16450{
16451 tSirLPHBInd *lphbInd;
16452 struct sk_buff *skb;
16453 hdd_context_t *pHddCtxt;
16454
16455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16456 "LPHB indication arrived");
16457
16458 if (pAdapter == NULL)
16459 {
16460 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16461 "%s: pAdapter is NULL\n",__func__);
16462 return;
16463 }
16464
16465 if (NULL == indCont)
16466 {
16467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16468 "LPHB IND, invalid argument");
16469 return;
16470 }
16471
16472 pHddCtxt = (hdd_context_t *)pAdapter;
16473 lphbInd = (tSirLPHBInd *)indCont;
16474 skb = cfg80211_testmode_alloc_event_skb(
16475 pHddCtxt->wiphy,
16476 sizeof(tSirLPHBInd),
16477 GFP_ATOMIC);
16478 if (!skb)
16479 {
16480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16481 "LPHB timeout, NL buffer alloc fail");
16482 return;
16483 }
16484
16485 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB))
16486 {
16487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16488 "WLAN_HDD_TM_ATTR_CMD put fail");
16489 goto nla_put_failure;
16490 }
16491 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType))
16492 {
16493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16494 "WLAN_HDD_TM_ATTR_TYPE put fail");
16495 goto nla_put_failure;
16496 }
16497 if(nla_put(skb, WLAN_HDD_TM_ATTR_DATA,
16498 sizeof(tSirLPHBInd), lphbInd))
16499 {
16500 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16501 "WLAN_HDD_TM_ATTR_DATA put fail");
16502 goto nla_put_failure;
16503 }
16504 cfg80211_testmode_event(skb, GFP_ATOMIC);
16505 return;
16506
16507nla_put_failure:
16508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16509 "NLA Put fail");
16510 kfree_skb(skb);
16511
16512 return;
16513}
16514#endif /* FEATURE_WLAN_LPHB */
16515
16516static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
16517{
16518 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16519 int err = 0;
16520#ifdef FEATURE_WLAN_LPHB
16521 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16522 eHalStatus smeStatus;
16523
16524 ENTER();
16525
16526 err = wlan_hdd_validate_context(pHddCtx);
16527 if (0 != err)
16528 {
16529 return err;
16530 }
16531#endif /* FEATURE_WLAN_LPHB */
16532
16533 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
16534 if (err)
16535 {
16536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16537 "%s Testmode INV ATTR", __func__);
16538 return err;
16539 }
16540
16541 if (!tb[WLAN_HDD_TM_ATTR_CMD])
16542 {
16543 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16544 "%s Testmode INV CMD", __func__);
16545 return -EINVAL;
16546 }
16547
16548 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
16549 TRACE_CODE_HDD_CFG80211_TESTMODE,
16550 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
16551 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
16552 {
16553#ifdef FEATURE_WLAN_LPHB
16554 /* Low Power Heartbeat configuration request */
16555 case WLAN_HDD_TM_CMD_WLAN_HB:
16556 {
16557 int buf_len;
16558 void *buf;
16559 tSirLPHBReq *hb_params = NULL;
16560 tSirLPHBReq *hb_params_temp = NULL;
16561
16562 if (!tb[WLAN_HDD_TM_ATTR_DATA])
16563 {
16564 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16565 "%s Testmode INV DATA", __func__);
16566 return -EINVAL;
16567 }
16568
16569 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16570 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16571
16572 hb_params_temp =(tSirLPHBReq *)buf;
16573 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID) &&
16574 (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0))
16575 return -EINVAL;
16576
chrmhoffmannbb97ca42017-05-13 21:27:44 +020016577 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
16578 if (NULL == hb_params)
16579 {
16580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16581 "%s Request Buffer Alloc Fail", __func__);
16582 return -EINVAL;
16583 }
16584
Gururaj Patil6b8abb32019-09-23 13:48:29 +000016585 vos_mem_zero(hb_params, sizeof(tSirLPHBReq));
chrmhoffmannbb97ca42017-05-13 21:27:44 +020016586 vos_mem_copy(hb_params, buf, buf_len);
16587 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
16588 hb_params,
16589 wlan_hdd_cfg80211_lphb_ind_handler);
16590 if (eHAL_STATUS_SUCCESS != smeStatus)
16591 {
16592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16593 "LPHB Config Fail, disable");
16594 vos_mem_free(hb_params);
16595 }
16596 return 0;
16597 }
16598#endif /* FEATURE_WLAN_LPHB */
16599 default:
16600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16601 "%s: unsupported event",__func__);
16602 return -EOPNOTSUPP;
16603 }
16604
16605 EXIT();
16606 return err;
16607}
16608
16609static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16610#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
16611 struct wireless_dev *wdev,
16612#endif
16613 void *data, int len)
16614{
16615 int ret;
16616
16617 vos_ssr_protect(__func__);
16618 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16619 vos_ssr_unprotect(__func__);
16620
16621 return ret;
16622}
16623#endif /* CONFIG_NL80211_TESTMODE */
16624
16625static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
16626 struct net_device *dev,
16627 int idx, struct survey_info *survey)
16628{
16629 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16630 hdd_context_t *pHddCtx;
16631 hdd_station_ctx_t *pHddStaCtx;
16632 tHalHandle halHandle;
16633 v_U32_t channel = 0, freq = 0; /* Initialization Required */
16634 v_S7_t snr,rssi;
16635 int status, i, j, filled = 0;
16636
16637 ENTER();
16638
16639 if (NULL == pAdapter)
16640 {
16641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
16642 "%s: HDD adapter is Null", __func__);
16643 return -ENODEV;
16644 }
16645
16646 if (NULL == wiphy)
16647 {
16648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
16649 "%s: wiphy is Null", __func__);
16650 return -ENODEV;
16651 }
16652
16653 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16654 status = wlan_hdd_validate_context(pHddCtx);
16655 if (0 != status)
16656 {
16657 return status;
16658 }
16659
16660 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16661
16662 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
16663 0 != pAdapter->survey_idx ||
16664 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
16665 {
16666 /* The survey dump ops when implemented completely is expected to
16667 * return a survey of all channels and the ops is called by the
16668 * kernel with incremental values of the argument 'idx' till it
16669 * returns -ENONET. But we can only support the survey for the
16670 * operating channel for now. survey_idx is used to track
16671 * that the ops is called only once and then return -ENONET for
16672 * the next iteration
16673 */
16674 pAdapter->survey_idx = 0;
16675 return -ENONET;
16676 }
16677
16678 if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario)
16679 {
16680 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16681 "%s: Roaming in progress, hence return ", __func__);
16682 return -ENONET;
16683 }
16684
16685 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16686
16687 wlan_hdd_get_snr(pAdapter, &snr);
16688 wlan_hdd_get_rssi(pAdapter, &rssi);
16689
16690 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
16691 TRACE_CODE_HDD_CFG80211_DUMP_SURVEY,
16692 pAdapter->sessionId, pAdapter->device_mode));
16693 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
16694 hdd_wlan_get_freq(channel, &freq);
16695
16696
16697 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
16698 {
16699 if (NULL == wiphy->bands[i])
16700 {
16701 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
16702 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
16703 continue;
16704 }
16705
16706 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
16707 {
16708 struct ieee80211_supported_band *band = wiphy->bands[i];
16709
16710 if (band->channels[j].center_freq == (v_U16_t)freq)
16711 {
16712 survey->channel = &band->channels[j];
16713 /* The Rx BDs contain SNR values in dB for the received frames
16714 * while the supplicant expects noise. So we calculate and
16715 * return the value of noise (dBm)
16716 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
16717 */
16718 survey->noise = rssi - snr;
16719 survey->filled = SURVEY_INFO_NOISE_DBM;
16720 filled = 1;
16721 }
16722 }
16723 }
16724
16725 if (filled)
16726 pAdapter->survey_idx = 1;
16727 else
16728 {
16729 pAdapter->survey_idx = 0;
16730 return -ENONET;
16731 }
16732
16733 EXIT();
16734 return 0;
16735}
16736
16737static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
16738 struct net_device *dev,
16739 int idx, struct survey_info *survey)
16740{
16741 int ret;
16742
16743 vos_ssr_protect(__func__);
16744 ret = __wlan_hdd_cfg80211_dump_survey(wiphy, dev, idx, survey);
16745 vos_ssr_unprotect(__func__);
16746
16747 return ret;
16748}
16749
16750/*
16751 * FUNCTION: __wlan_hdd_cfg80211_resume_wlan
16752 * this is called when cfg80211 driver resume
16753 * driver updates latest sched_scan scan result(if any) to cfg80211 database
16754 */
16755int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
16756{
16757 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16758 hdd_adapter_t *pAdapter;
16759 hdd_adapter_list_node_t *pAdapterNode, *pNext;
16760 VOS_STATUS status = VOS_STATUS_SUCCESS;
16761
16762 ENTER();
16763
16764 if (0 != wlan_hdd_validate_context(pHddCtx))
16765 {
16766 return 0;
16767 }
16768
16769 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_CFG80211_RESUME_WLAN,
16770 NO_SESSION, pHddCtx->isWiphySuspended));
16771 spin_lock(&pHddCtx->schedScan_lock);
16772 pHddCtx->isWiphySuspended = FALSE;
16773 if (TRUE != pHddCtx->isSchedScanUpdatePending)
16774 {
16775 spin_unlock(&pHddCtx->schedScan_lock);
16776 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16777 "%s: Return resume is not due to PNO indication", __func__);
16778 return 0;
16779 }
16780 // Reset flag to avoid updatating cfg80211 data old results again
16781 pHddCtx->isSchedScanUpdatePending = FALSE;
16782 spin_unlock(&pHddCtx->schedScan_lock);
16783
16784 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
16785
16786 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
16787 {
16788 pAdapter = pAdapterNode->pAdapter;
16789 if ( (NULL != pAdapter) &&
16790 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
16791 {
16792 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
16793 {
16794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
16795 "%s: NO SCAN result", __func__);
16796 }
16797 else
16798 {
16799 /* Acquire wakelock to handle the case where APP's tries to
16800 * suspend immediately after updating the scan results. Whis
16801 * results in app's is in suspended state and not able to
16802 * process the connect request to AP
16803 */
16804 hdd_prevent_suspend_timeout(2000,
16805 WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN);
16806 cfg80211_sched_scan_results(pHddCtx->wiphy);
16807 }
16808
16809 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16810 "%s : cfg80211 scan result database updated", __func__);
16811
16812 EXIT();
16813 return 0;
16814
16815 }
16816 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
16817 pAdapterNode = pNext;
16818 }
16819
16820 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
16821 "%s: Failed to find Adapter", __func__);
16822 EXIT();
16823 return 0;
16824}
16825
16826int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
16827{
16828 int ret;
16829
16830 vos_ssr_protect(__func__);
16831 ret = __wlan_hdd_cfg80211_resume_wlan(wiphy);
16832 vos_ssr_unprotect(__func__);
16833
16834 return ret;
16835}
16836
16837/*
16838 * FUNCTION: __wlan_hdd_cfg80211_suspend_wlan
16839 * this is called when cfg80211 driver suspends
16840 */
16841int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
16842 struct cfg80211_wowlan *wow)
16843{
16844 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16845 int ret = 0;
16846
16847 ENTER();
16848
16849 ret = wlan_hdd_validate_context(pHddCtx);
16850 if (0 != ret)
16851 {
16852 return ret;
16853 }
16854
16855
16856 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
16857 TRACE_CODE_HDD_CFG80211_SUSPEND_WLAN,
16858 NO_SESSION, pHddCtx->isWiphySuspended));
16859 pHddCtx->isWiphySuspended = TRUE;
16860
16861 EXIT();
16862
16863 return 0;
16864}
16865
16866int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
16867 struct cfg80211_wowlan *wow)
16868{
16869 int ret;
16870
16871 vos_ssr_protect(__func__);
16872 ret = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
16873 vos_ssr_unprotect(__func__);
16874
16875 return ret;
16876}
16877/* cfg80211_ops */
16878static struct cfg80211_ops wlan_hdd_cfg80211_ops =
16879{
16880 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16881 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16882 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16883 .change_station = wlan_hdd_change_station,
16884#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
16885 .add_beacon = wlan_hdd_cfg80211_add_beacon,
16886 .del_beacon = wlan_hdd_cfg80211_del_beacon,
16887 .set_beacon = wlan_hdd_cfg80211_set_beacon,
16888#else
16889 .start_ap = wlan_hdd_cfg80211_start_ap,
16890 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16891 .stop_ap = wlan_hdd_cfg80211_stop_ap,
16892#endif
16893 .change_bss = wlan_hdd_cfg80211_change_bss,
16894 .add_key = wlan_hdd_cfg80211_add_key,
16895 .get_key = wlan_hdd_cfg80211_get_key,
16896 .del_key = wlan_hdd_cfg80211_del_key,
16897 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16898#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
16899 .set_channel = wlan_hdd_cfg80211_set_channel,
16900#endif
16901 .scan = wlan_hdd_cfg80211_scan,
16902 .connect = wlan_hdd_cfg80211_connect,
16903 .disconnect = wlan_hdd_cfg80211_disconnect,
16904 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16905 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16906 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16907 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16908 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16909 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16910 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16911 .mgmt_tx = wlan_hdd_mgmt_tx,
16912#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
16913 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16914 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16915 .set_txq_params = wlan_hdd_set_txq_params,
16916#endif
16917 .get_station = wlan_hdd_cfg80211_get_station,
16918 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16919 .del_station = wlan_hdd_cfg80211_del_station,
16920 .add_station = wlan_hdd_cfg80211_add_station,
16921#ifdef FEATURE_WLAN_LFR
16922 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16923 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16924 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
16925#endif
16926#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
16927 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16928#endif
16929#ifdef FEATURE_WLAN_TDLS
16930 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16931 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16932#endif
16933#ifdef WLAN_FEATURE_GTK_OFFLOAD
16934 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16935#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16936#ifdef FEATURE_WLAN_SCAN_PNO
16937 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16938 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16939#endif /*FEATURE_WLAN_SCAN_PNO */
16940 .resume = wlan_hdd_cfg80211_resume_wlan,
16941 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16942 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16943#ifdef WLAN_NL80211_TESTMODE
16944 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16945#endif
16946 .dump_survey = wlan_hdd_cfg80211_dump_survey,
16947};