blob: 58315c3a23d4e0aebb363d3991444b35ef58f424 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 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/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -080023 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
24 * All Rights Reserved.
25 * Qualcomm Atheros Confidential and Proprietary.
Kiet Lam842dad02014-02-18 18:44:02 -080026 *
Kiet Lamaa8e15a2014-02-11 23:30:06 -080027 */
Kiet Lam842dad02014-02-18 18:44:02 -080028
29
Jeff Johnson295189b2012-06-20 16:38:30 -070030/**========================================================================
31
32 \file wlan_hdd_cfg80211.c
33
34 \brief WLAN Host Device Driver implementation
35
Jeff Johnson295189b2012-06-20 16:38:30 -070036 ========================================================================*/
37
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070038/**=========================================================================
Jeff Johnson295189b2012-06-20 16:38:30 -070039
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070040 EDIT HISTORY FOR FILE
Jeff Johnson295189b2012-06-20 16:38:30 -070041
42
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070043 This section contains comments describing changes made to the module.
44 Notice that changes are listed in reverse chronological order.
Jeff Johnson295189b2012-06-20 16:38:30 -070045
46
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070047 $Header:$ $DateTime: $ $Author: $
Jeff Johnson295189b2012-06-20 16:38:30 -070048
49
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070050 when who what, where, why
Jeff Johnson295189b2012-06-20 16:38:30 -070051 -------- --- --------------------------------------------------------
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070052 21/12/09 Ashwani Created module.
Jeff Johnson295189b2012-06-20 16:38:30 -070053
54 07/06/10 Kumar Deepak Implemented cfg80211 callbacks for ANDROID
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -070055 Ganesh K
Jeff Johnson295189b2012-06-20 16:38:30 -070056 ==========================================================================*/
57
Jeff Johnson295189b2012-06-20 16:38:30 -070058
59#include <linux/version.h>
60#include <linux/module.h>
61#include <linux/kernel.h>
62#include <linux/init.h>
63#include <linux/wireless.h>
64#include <wlan_hdd_includes.h>
65#include <net/arp.h>
66#include <net/cfg80211.h>
67#include <linux/wireless.h>
68#include <wlan_hdd_wowl.h>
69#include <aniGlobal.h>
70#include "ccmApi.h"
71#include "sirParams.h"
72#include "dot11f.h"
73#include "wlan_hdd_assoc.h"
74#include "wlan_hdd_wext.h"
75#include "sme_Api.h"
76#include "wlan_hdd_p2p.h"
77#include "wlan_hdd_cfg80211.h"
78#include "wlan_hdd_hostapd.h"
79#include "sapInternal.h"
80#include "wlan_hdd_softap_tx_rx.h"
81#include "wlan_hdd_main.h"
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +053082#include "wlan_hdd_assoc.h"
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053083#include "wlan_hdd_power.h"
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053084#include "wlan_hdd_trace.h"
85#include "vos_types.h"
86#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070087#ifdef WLAN_BTAMP_FEATURE
88#include "bap_hdd_misc.h"
89#endif
90#include <qc_sap_ioctl.h>
Mohit Khanna698ba2a2012-12-04 15:08:18 -080091#ifdef FEATURE_WLAN_TDLS
92#include "wlan_hdd_tdls.h"
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053093#include "wlan_hdd_wmm.h"
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053094#include "wlan_qct_wda.h"
Mohit Khanna698ba2a2012-12-04 15:08:18 -080095#endif
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +053096#include "wlan_nv.h"
Leo Chang6fe1f922013-06-07 19:21:24 -070097#include "wlan_hdd_dev_pwr.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070098
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)
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700103#define MAX_SCAN_SSID 9
Kiet Lamac06e2c2013-10-23 16:25:07 +0530104#define MAX_PENDING_LOG 5
Jeff Johnson295189b2012-06-20 16:38:30 -0700105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) ( lenInBss + sizeof(lenInBss) - \
krunal soni2a6a9062014-02-11 14:14:23 -0800106 ((uintptr_t)OFFSET_OF( tSirBssDescription, ieFields)))
Jeff Johnson295189b2012-06-20 16:38:30 -0700107
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
Lee Hoonkic1262f22013-01-24 21:59:00 -0800133#ifndef WLAN_FEATURE_TDLS_DEBUG
134#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
135#else
136#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
137#endif
138
Gopichand Nakkala356fb102013-03-06 12:34:04 +0530139#ifdef WLAN_FEATURE_VOWIFI_11R
140#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
141#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
142#endif
143
Naresh Jayaram3180aa42014-02-12 21:47:26 +0530144#define HDD_CHANNEL_14 14
145
Sunil Duttc69bccb2014-05-26 21:30:20 +0530146#ifdef WLAN_FEATURE_LINK_LAYER_STATS
147/*
148 * Used to allocate the size of 4096 for the link layer stats.
149 * The size of 4096 is considered assuming that all data per
150 * respective event fit with in the limit.Please take a call
151 * on the limit based on the data requirements on link layer
152 * statistics.
153 */
154#define LL_STATS_EVENT_BUF_SIZE 4096
155#endif
Dino Mycle6fb96c12014-06-10 11:52:40 +0530156#ifdef WLAN_FEATURE_EXTSCAN
157/*
158 * Used to allocate the size of 4096 for the EXTScan NL data.
159 * The size of 4096 is considered assuming that all data per
160 * respective event fit with in the limit.Please take a call
161 * on the limit based on the data requirements.
162 */
163
164#define EXTSCAN_EVENT_BUF_SIZE 4096
165#define EXTSCAN_MAX_CACHED_RESULTS_PER_IND 32
166#endif
Sunil Duttc69bccb2014-05-26 21:30:20 +0530167
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530168static const u32 hdd_cipher_suites[] =
Jeff Johnson295189b2012-06-20 16:38:30 -0700169{
170 WLAN_CIPHER_SUITE_WEP40,
171 WLAN_CIPHER_SUITE_WEP104,
172 WLAN_CIPHER_SUITE_TKIP,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800173#ifdef FEATURE_WLAN_ESE
Jeff Johnson295189b2012-06-20 16:38:30 -0700174#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
175 WLAN_CIPHER_SUITE_KRK,
176 WLAN_CIPHER_SUITE_CCMP,
177#else
178 WLAN_CIPHER_SUITE_CCMP,
179#endif
180#ifdef FEATURE_WLAN_WAPI
181 WLAN_CIPHER_SUITE_SMS4,
182#endif
Chet Lanctot186b5732013-03-18 10:26:30 -0700183#ifdef WLAN_FEATURE_11W
184 WLAN_CIPHER_SUITE_AES_CMAC,
185#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700186};
187
188static inline int is_broadcast_ether_addr(const u8 *addr)
189{
190 return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&
191 (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
192}
193
194static struct ieee80211_channel hdd_channels_2_4_GHZ[] =
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530195{
Jeff Johnson295189b2012-06-20 16:38:30 -0700196 HDD2GHZCHAN(2412, 1, 0) ,
197 HDD2GHZCHAN(2417, 2, 0) ,
198 HDD2GHZCHAN(2422, 3, 0) ,
199 HDD2GHZCHAN(2427, 4, 0) ,
200 HDD2GHZCHAN(2432, 5, 0) ,
201 HDD2GHZCHAN(2437, 6, 0) ,
202 HDD2GHZCHAN(2442, 7, 0) ,
203 HDD2GHZCHAN(2447, 8, 0) ,
204 HDD2GHZCHAN(2452, 9, 0) ,
205 HDD2GHZCHAN(2457, 10, 0) ,
206 HDD2GHZCHAN(2462, 11, 0) ,
207 HDD2GHZCHAN(2467, 12, 0) ,
208 HDD2GHZCHAN(2472, 13, 0) ,
209 HDD2GHZCHAN(2484, 14, 0) ,
210};
211
Jeff Johnson295189b2012-06-20 16:38:30 -0700212static struct ieee80211_channel hdd_social_channels_2_4_GHZ[] =
213{
214 HDD2GHZCHAN(2412, 1, 0) ,
215 HDD2GHZCHAN(2437, 6, 0) ,
216 HDD2GHZCHAN(2462, 11, 0) ,
217};
Jeff Johnson295189b2012-06-20 16:38:30 -0700218
219static struct ieee80211_channel hdd_channels_5_GHZ[] =
220{
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -0700221 HDD5GHZCHAN(4920, 240, 0) ,
222 HDD5GHZCHAN(4940, 244, 0) ,
223 HDD5GHZCHAN(4960, 248, 0) ,
224 HDD5GHZCHAN(4980, 252, 0) ,
225 HDD5GHZCHAN(5040, 208, 0) ,
226 HDD5GHZCHAN(5060, 212, 0) ,
227 HDD5GHZCHAN(5080, 216, 0) ,
Jeff Johnson295189b2012-06-20 16:38:30 -0700228 HDD5GHZCHAN(5180, 36, 0) ,
229 HDD5GHZCHAN(5200, 40, 0) ,
230 HDD5GHZCHAN(5220, 44, 0) ,
231 HDD5GHZCHAN(5240, 48, 0) ,
232 HDD5GHZCHAN(5260, 52, 0) ,
233 HDD5GHZCHAN(5280, 56, 0) ,
234 HDD5GHZCHAN(5300, 60, 0) ,
235 HDD5GHZCHAN(5320, 64, 0) ,
236 HDD5GHZCHAN(5500,100, 0) ,
237 HDD5GHZCHAN(5520,104, 0) ,
238 HDD5GHZCHAN(5540,108, 0) ,
239 HDD5GHZCHAN(5560,112, 0) ,
240 HDD5GHZCHAN(5580,116, 0) ,
241 HDD5GHZCHAN(5600,120, 0) ,
242 HDD5GHZCHAN(5620,124, 0) ,
243 HDD5GHZCHAN(5640,128, 0) ,
244 HDD5GHZCHAN(5660,132, 0) ,
245 HDD5GHZCHAN(5680,136, 0) ,
246 HDD5GHZCHAN(5700,140, 0) ,
Leo Chang80de3c22013-11-26 10:52:12 -0800247#ifdef FEATURE_WLAN_CH144
248 HDD5GHZCHAN(5720,144, 0) ,
249#endif /* FEATURE_WLAN_CH144 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 HDD5GHZCHAN(5745,149, 0) ,
251 HDD5GHZCHAN(5765,153, 0) ,
252 HDD5GHZCHAN(5785,157, 0) ,
253 HDD5GHZCHAN(5805,161, 0) ,
254 HDD5GHZCHAN(5825,165, 0) ,
255};
256
257static struct ieee80211_rate g_mode_rates[] =
258{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530259 HDD_G_MODE_RATETAB(10, 0x1, 0),
260 HDD_G_MODE_RATETAB(20, 0x2, 0),
261 HDD_G_MODE_RATETAB(55, 0x4, 0),
262 HDD_G_MODE_RATETAB(110, 0x8, 0),
263 HDD_G_MODE_RATETAB(60, 0x10, 0),
264 HDD_G_MODE_RATETAB(90, 0x20, 0),
265 HDD_G_MODE_RATETAB(120, 0x40, 0),
266 HDD_G_MODE_RATETAB(180, 0x80, 0),
267 HDD_G_MODE_RATETAB(240, 0x100, 0),
268 HDD_G_MODE_RATETAB(360, 0x200, 0),
269 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 HDD_G_MODE_RATETAB(540, 0x800, 0),
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530271};
Jeff Johnson295189b2012-06-20 16:38:30 -0700272
273static struct ieee80211_rate a_mode_rates[] =
274{
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530275 HDD_G_MODE_RATETAB(60, 0x10, 0),
276 HDD_G_MODE_RATETAB(90, 0x20, 0),
277 HDD_G_MODE_RATETAB(120, 0x40, 0),
278 HDD_G_MODE_RATETAB(180, 0x80, 0),
279 HDD_G_MODE_RATETAB(240, 0x100, 0),
280 HDD_G_MODE_RATETAB(360, 0x200, 0),
281 HDD_G_MODE_RATETAB(480, 0x400, 0),
Jeff Johnson295189b2012-06-20 16:38:30 -0700282 HDD_G_MODE_RATETAB(540, 0x800, 0),
283};
284
285static struct ieee80211_supported_band wlan_hdd_band_2_4_GHZ =
286{
287 .channels = hdd_channels_2_4_GHZ,
288 .n_channels = ARRAY_SIZE(hdd_channels_2_4_GHZ),
289 .band = IEEE80211_BAND_2GHZ,
290 .bitrates = g_mode_rates,
291 .n_bitrates = g_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
297 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
298 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
299 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
300 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
301 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
302};
303
Jeff Johnson295189b2012-06-20 16:38:30 -0700304static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_GHZ =
305{
306 .channels = hdd_social_channels_2_4_GHZ,
307 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_GHZ),
308 .band = IEEE80211_BAND_2GHZ,
309 .bitrates = g_mode_rates,
310 .n_bitrates = g_mode_rates_size,
311 .ht_cap.ht_supported = 1,
312 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
313 | IEEE80211_HT_CAP_GRN_FLD
314 | IEEE80211_HT_CAP_DSSSCCK40
315 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
316 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
317 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
318 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
319 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
320 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
321};
Jeff Johnson295189b2012-06-20 16:38:30 -0700322
323static struct ieee80211_supported_band wlan_hdd_band_5_GHZ =
324{
325 .channels = hdd_channels_5_GHZ,
326 .n_channels = ARRAY_SIZE(hdd_channels_5_GHZ),
327 .band = IEEE80211_BAND_5GHZ,
328 .bitrates = a_mode_rates,
329 .n_bitrates = a_mode_rates_size,
330 .ht_cap.ht_supported = 1,
331 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
332 | IEEE80211_HT_CAP_GRN_FLD
333 | IEEE80211_HT_CAP_DSSSCCK40
334 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
335 | IEEE80211_HT_CAP_SGI_40
336 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
337 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
338 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
339 .ht_cap.mcs.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
340 .ht_cap.mcs.rx_highest = cpu_to_le16( 72 ),
341 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
342};
343
Gopichand Nakkala747461f2013-04-24 19:24:45 +0530344/* This structure contain information what kind of frame are expected in
Jeff Johnson295189b2012-06-20 16:38:30 -0700345 TX/RX direction for each kind of interface */
346static const struct ieee80211_txrx_stypes
347wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
348 [NL80211_IFTYPE_STATION] = {
349 .tx = 0xffff,
350 .rx = BIT(SIR_MAC_MGMT_ACTION) |
351 BIT(SIR_MAC_MGMT_PROBE_REQ),
352 },
353 [NL80211_IFTYPE_AP] = {
354 .tx = 0xffff,
355 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
357 BIT(SIR_MAC_MGMT_PROBE_REQ) |
358 BIT(SIR_MAC_MGMT_DISASSOC) |
359 BIT(SIR_MAC_MGMT_AUTH) |
360 BIT(SIR_MAC_MGMT_DEAUTH) |
361 BIT(SIR_MAC_MGMT_ACTION),
362 },
Jeff Johnsonbc006202013-04-29 14:05:30 -0700363 [NL80211_IFTYPE_ADHOC] = {
364 .tx = 0xffff,
365 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
366 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
367 BIT(SIR_MAC_MGMT_PROBE_REQ) |
368 BIT(SIR_MAC_MGMT_DISASSOC) |
369 BIT(SIR_MAC_MGMT_AUTH) |
370 BIT(SIR_MAC_MGMT_DEAUTH) |
371 BIT(SIR_MAC_MGMT_ACTION),
372 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700373 [NL80211_IFTYPE_P2P_CLIENT] = {
374 .tx = 0xffff,
375 .rx = BIT(SIR_MAC_MGMT_ACTION) |
376 BIT(SIR_MAC_MGMT_PROBE_REQ),
377 },
378 [NL80211_IFTYPE_P2P_GO] = {
379 /* This is also same as for SoftAP */
380 .tx = 0xffff,
381 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
382 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
383 BIT(SIR_MAC_MGMT_PROBE_REQ) |
384 BIT(SIR_MAC_MGMT_DISASSOC) |
385 BIT(SIR_MAC_MGMT_AUTH) |
386 BIT(SIR_MAC_MGMT_DEAUTH) |
387 BIT(SIR_MAC_MGMT_ACTION),
388 },
Jeff Johnson295189b2012-06-20 16:38:30 -0700389};
390
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800391#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800392static const struct ieee80211_iface_limit
393wlan_hdd_iface_limit[] = {
394 {
Sunil Ravia72c3992013-01-31 06:12:22 -0800395 /* max = 3 ; Our driver create two interfaces during driver init
396 * wlan0 and p2p0 interfaces. p2p0 is considered as station
397 * interface until a group is formed. In JB architecture, once the
398 * group is formed, interface type of p2p0 is changed to P2P GO or
399 * Client.
400 * When supplicant remove the group, it first issue a set interface
401 * cmd to change the mode back to Station. In JB this works fine as
402 * we advertize two station type interface during driver init.
403 * Some vendors create separate interface for P2P GO/Client,
404 * after group formation(Third one). But while group remove
405 * supplicant first tries to change the mode(3rd interface) to STATION
406 * But as we advertized only two sta type interfaces nl80211 was
407 * returning error for the third one which was leading to failure in
408 * delete interface. Ideally while removing the group, supplicant
409 * should not try to change the 3rd interface mode to Station type.
410 * Till we get a fix in wpa_supplicant, we advertize max STA
411 * interface type to 3
412 */
413 .max = 3,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800414 .types = BIT(NL80211_IFTYPE_STATION),
415 },
416 {
417 .max = 1,
Jeff Johnsonbc006202013-04-29 14:05:30 -0700418 .types = BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP),
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800419 },
420 {
421 .max = 1,
422 .types = BIT(NL80211_IFTYPE_P2P_GO) |
423 BIT(NL80211_IFTYPE_P2P_CLIENT),
424 },
425};
426
427/* By default, only single channel concurrency is allowed */
428static struct ieee80211_iface_combination
429wlan_hdd_iface_combination = {
430 .limits = wlan_hdd_iface_limit,
431 .num_different_channels = 1,
Sunil Ravia72c3992013-01-31 06:12:22 -0800432 /*
433 * max = WLAN_MAX_INTERFACES ; JellyBean architecture creates wlan0
434 * and p2p0 interfaces during driver init
435 * Some vendors create separate interface for P2P operations.
436 * wlan0: STA interface
437 * p2p0: P2P Device interface, action frames goes
438 * through this interface.
439 * p2p-xx: P2P interface, After GO negotiation this interface is
440 * created for p2p operations(GO/CLIENT interface).
441 */
442 .max_interfaces = WLAN_MAX_INTERFACES,
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800443 .n_limits = ARRAY_SIZE(wlan_hdd_iface_limit),
444 .beacon_int_infra_match = false,
445};
446#endif
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -0800447
Jeff Johnson295189b2012-06-20 16:38:30 -0700448static struct cfg80211_ops wlan_hdd_cfg80211_ops;
449
450/* Data rate 100KBPS based on IE Index */
451struct index_data_rate_type
452{
453 v_U8_t beacon_rate_index;
454 v_U16_t supported_rate[4];
455};
456
457/* 11B, 11G Rate table include Basic rate and Extended rate
458 The IDX field is the rate index
459 The HI field is the rate when RSSI is strong or being ignored
460 (in this case we report actual rate)
461 The MID field is the rate when RSSI is moderate
462 (in this case we cap 11b rates at 5.5 and 11g rates at 24)
463 The LO field is the rate when RSSI is low
464 (in this case we don't report rates, actual current rate used)
465 */
466static const struct
467{
468 v_U8_t beacon_rate_index;
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700469 v_U16_t supported_rate[4];
Jeff Johnson295189b2012-06-20 16:38:30 -0700470} supported_data_rate[] =
471{
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -0700472/* IDX HI HM LM LO (RSSI-based index */
473 {2, { 10, 10, 10, 0}},
474 {4, { 20, 20, 10, 0}},
475 {11, { 55, 20, 10, 0}},
476 {12, { 60, 55, 20, 0}},
477 {18, { 90, 55, 20, 0}},
478 {22, {110, 55, 20, 0}},
479 {24, {120, 90, 60, 0}},
480 {36, {180, 120, 60, 0}},
481 {44, {220, 180, 60, 0}},
482 {48, {240, 180, 90, 0}},
483 {66, {330, 180, 90, 0}},
484 {72, {360, 240, 90, 0}},
485 {96, {480, 240, 120, 0}},
486 {108, {540, 240, 120, 0}}
Jeff Johnson295189b2012-06-20 16:38:30 -0700487};
488
489/* MCS Based rate table */
490static struct index_data_rate_type supported_mcs_rate[] =
491{
492/* MCS L20 L40 S20 S40 */
493 {0, {65, 135, 72, 150}},
494 {1, {130, 270, 144, 300}},
495 {2, {195, 405, 217, 450}},
496 {3, {260, 540, 289, 600}},
497 {4, {390, 810, 433, 900}},
498 {5, {520, 1080, 578, 1200}},
499 {6, {585, 1215, 650, 1350}},
500 {7, {650, 1350, 722, 1500}}
501};
502
Leo Chang6f8870f2013-03-26 18:11:36 -0700503#ifdef WLAN_FEATURE_11AC
504
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530505#define DATA_RATE_11AC_MCS_MASK 0x03
Leo Chang6f8870f2013-03-26 18:11:36 -0700506
507struct index_vht_data_rate_type
508{
509 v_U8_t beacon_rate_index;
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530510 v_U16_t supported_VHT80_rate[2];
511 v_U16_t supported_VHT40_rate[2];
512 v_U16_t supported_VHT20_rate[2];
Leo Chang6f8870f2013-03-26 18:11:36 -0700513};
514
515typedef enum
516{
517 DATA_RATE_11AC_MAX_MCS_7,
518 DATA_RATE_11AC_MAX_MCS_8,
519 DATA_RATE_11AC_MAX_MCS_9,
520 DATA_RATE_11AC_MAX_MCS_NA
521} eDataRate11ACMaxMcs;
522
523/* MCS Based VHT rate table */
524static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
525{
Gopichand Nakkala4c705372013-04-24 13:20:33 +0530526/* MCS L80 S80 L40 S40 L20 S40*/
527 {0, {293, 325}, {135, 150}, {65, 72}},
528 {1, {585, 650}, {270, 300}, {130, 144}},
529 {2, {878, 975}, {405, 450}, {195, 217}},
530 {3, {1170, 1300}, {540, 600}, {260, 289}},
531 {4, {1755, 1950}, {810, 900}, {390, 433}},
532 {5, {2340, 2600}, {1080, 1200}, {520, 578}},
533 {6, {2633, 2925}, {1215, 1350}, {585, 650}},
534 {7, {2925, 3250}, {1350, 1500}, {650, 722}},
535 {8, {3510, 3900}, {1620, 1800}, {780, 867}},
536 {9, {3900, 4333}, {1800, 2000}, {780, 867}}
Leo Chang6f8870f2013-03-26 18:11:36 -0700537};
538#endif /* WLAN_FEATURE_11AC */
539
c_hpothu79aab322014-07-14 21:11:01 +0530540/*array index points to MCS and array value points respective rssi*/
541static int rssiMcsTbl[][10] =
542{
543/*MCS 0 1 2 3 4 5 6 7 8 9*/
544 {-82, -79, -77, -74, -70, -66, -65, -64, -59, -57}, //20
545 {-79, -76, -74, -71, -67, -63, -62, -61, -56, -54}, //40
546 {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} //80
547};
548
Jeff Johnson295189b2012-06-20 16:38:30 -0700549extern struct net_device_ops net_ops_struct;
550
Leo Chang9056f462013-08-01 19:21:11 -0700551#ifdef WLAN_NL80211_TESTMODE
552enum wlan_hdd_tm_attr
553{
554 WLAN_HDD_TM_ATTR_INVALID = 0,
555 WLAN_HDD_TM_ATTR_CMD = 1,
556 WLAN_HDD_TM_ATTR_DATA = 2,
557 WLAN_HDD_TM_ATTR_TYPE = 3,
558 /* keep last */
559 WLAN_HDD_TM_ATTR_AFTER_LAST,
560 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
561};
562
563enum wlan_hdd_tm_cmd
564{
565 WLAN_HDD_TM_CMD_WLAN_HB = 1,
566};
567
568#define WLAN_HDD_TM_DATA_MAX_LEN 5000
569
570static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] =
571{
572 [WLAN_HDD_TM_ATTR_CMD] = { .type = NLA_U32 },
573 [WLAN_HDD_TM_ATTR_DATA] = { .type = NLA_BINARY,
574 .len = WLAN_HDD_TM_DATA_MAX_LEN },
575};
576#endif /* WLAN_NL80211_TESTMODE */
577
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800578#ifdef FEATURE_WLAN_CH_AVOID
579/*
580 * FUNCTION: wlan_hdd_send_avoid_freq_event
581 * This is called when wlan driver needs to send vendor specific
582 * avoid frequency range event to userspace
583 */
584int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
585 tHddAvoidFreqList *pAvoidFreqList)
586{
587 struct sk_buff *vendor_event;
588
589 ENTER();
590
591 if (!pHddCtx)
592 {
593 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
594 "%s: HDD context is null", __func__);
595 return -1;
596 }
597
598 if (!pAvoidFreqList)
599 {
600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
601 "%s: pAvoidFreqList is null", __func__);
602 return -1;
603 }
604
605 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
606 sizeof(tHddAvoidFreqList),
Sunil Duttc69bccb2014-05-26 21:30:20 +0530607 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
Rajesh Chauhan98a31f82014-01-06 20:15:25 -0800608 GFP_KERNEL);
609 if (!vendor_event)
610 {
611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
612 "%s: cfg80211_vendor_event_alloc failed", __func__);
613 return -1;
614 }
615
616 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
617 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
618
619 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
620
621 EXIT();
622 return 0;
623}
624#endif /* FEATURE_WLAN_CH_AVOID */
625
Sunil Duttc69bccb2014-05-26 21:30:20 +0530626#ifdef WLAN_FEATURE_LINK_LAYER_STATS
627
628static v_BOOL_t put_wifi_rate_stat( tpSirWifiRateStat stats,
629 struct sk_buff *vendor_event)
630{
631 if (nla_put_u8(vendor_event,
632 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE,
633 stats->rate.preamble) ||
634 nla_put_u8(vendor_event,
635 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS,
636 stats->rate.nss) ||
637 nla_put_u8(vendor_event,
638 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW,
639 stats->rate.bw) ||
640 nla_put_u8(vendor_event,
641 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX,
642 stats->rate.rateMcsIdx) ||
643 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE,
644 stats->rate.bitrate ) ||
645 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU,
646 stats->txMpdu ) ||
647 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU,
648 stats->rxMpdu ) ||
649 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST,
650 stats->mpduLost ) ||
651 nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES,
652 stats->retries) ||
653 nla_put_u32(vendor_event,
654 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT,
655 stats->retriesShort ) ||
656 nla_put_u32(vendor_event,
657 QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG,
658 stats->retriesLong))
659 {
660 hddLog(VOS_TRACE_LEVEL_ERROR,
661 FL("QCA_WLAN_VENDOR_ATTR put fail"));
662 return FALSE;
663 }
664 return TRUE;
665}
666
667static v_BOOL_t put_wifi_peer_info( tpSirWifiPeerInfo stats,
668 struct sk_buff *vendor_event)
669{
670 u32 i = 0;
671 struct nlattr *rateInfo;
672 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE,
673 stats->type) ||
674 nla_put(vendor_event,
675 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS,
676 VOS_MAC_ADDR_SIZE, &stats->peerMacAddress[0]) ||
677 nla_put_u32(vendor_event,
678 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES,
679 stats->capabilities) ||
680 nla_put_u32(vendor_event,
681 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES,
682 stats->numRate))
683 {
684 hddLog(VOS_TRACE_LEVEL_ERROR,
685 FL("QCA_WLAN_VENDOR_ATTR put fail"));
686 goto error;
687 }
688
689 rateInfo = nla_nest_start(vendor_event,
690 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO);
691 for (i = 0; i < stats->numRate; i++)
692 {
693 struct nlattr *rates;
694 tpSirWifiRateStat pRateStats = (tpSirWifiRateStat )((uint8 *)
695 stats->rateStats +
696 (i * sizeof(tSirWifiRateStat)));
697 rates = nla_nest_start(vendor_event, i);
698
699 if (FALSE == put_wifi_rate_stat(pRateStats, vendor_event))
700 {
701 hddLog(VOS_TRACE_LEVEL_ERROR,
702 FL("QCA_WLAN_VENDOR_ATTR put fail"));
703 return FALSE;
704 }
705 nla_nest_end(vendor_event, rates);
706 }
707 nla_nest_end(vendor_event, rateInfo);
708
709 return TRUE;
710error:
711 return FALSE;
712}
713
714static v_BOOL_t put_wifi_wmm_ac_stat( tpSirWifiWmmAcStat stats,
715 struct sk_buff *vendor_event)
716{
717 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC,
718 stats->ac ) ||
719 nla_put_u32(vendor_event,
720 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU,
721 stats->txMpdu ) ||
722 nla_put_u32(vendor_event,
723 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU,
724 stats->rxMpdu ) ||
725 nla_put_u32(vendor_event,
726 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST,
727 stats->txMcast ) ||
728 nla_put_u32(vendor_event,
729 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST,
730 stats->rxMcast ) ||
731 nla_put_u32(vendor_event,
732 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU,
733 stats->rxAmpdu ) ||
734 nla_put_u32(vendor_event,
735 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU,
736 stats->txAmpdu ) ||
737 nla_put_u32(vendor_event,
738 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST,
739 stats->mpduLost )||
740 nla_put_u32(vendor_event,
741 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES,
742 stats->retries ) ||
743 nla_put_u32(vendor_event,
744 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT,
745 stats->retriesShort ) ||
746 nla_put_u32(vendor_event,
747 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG,
748 stats->retriesLong ) ||
749 nla_put_u32(vendor_event,
750 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN,
751 stats->contentionTimeMin ) ||
752 nla_put_u32(vendor_event,
753 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX,
754 stats->contentionTimeMax ) ||
755 nla_put_u32(vendor_event,
756 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG,
757 stats->contentionTimeAvg ) ||
758 nla_put_u32(vendor_event,
759 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES,
760 stats->contentionNumSamples ))
761 {
762 hddLog(VOS_TRACE_LEVEL_ERROR,
763 FL("QCA_WLAN_VENDOR_ATTR put fail") );
764 return FALSE;
765 }
766 return TRUE;
767}
768
769static v_BOOL_t put_wifi_interface_info(tpSirWifiInterfaceInfo stats,
770 struct sk_buff *vendor_event)
771{
772 if (nla_put_u32(vendor_event,
773 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE, stats->mode ) ||
774 nla_put(vendor_event,
775 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR,
776 VOS_MAC_ADDR_SIZE, stats->macAddr) ||
777 nla_put_u32(vendor_event,
778 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE,
779 stats->state ) ||
780 nla_put_u32(vendor_event,
781 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING,
782 stats->roaming ) ||
783 nla_put_u32(vendor_event,
784 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES,
785 stats->capabilities ) ||
786 nla_put(vendor_event,
787 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID,
788 strlen(stats->ssid), stats->ssid) ||
789 nla_put(vendor_event,
790 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID,
791 WNI_CFG_BSSID_LEN, stats->bssid) ||
792 nla_put(vendor_event,
793 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR,
794 WNI_CFG_COUNTRY_CODE_LEN, stats->apCountryStr) ||
795 nla_put(vendor_event,
796 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR,
797 WNI_CFG_COUNTRY_CODE_LEN, stats->countryStr)
798 )
799 {
800 hddLog(VOS_TRACE_LEVEL_ERROR,
801 FL("QCA_WLAN_VENDOR_ATTR put fail") );
802 return FALSE;
803 }
804 return TRUE;
805}
806
807static v_BOOL_t put_wifi_iface_stats(tpSirWifiIfaceStat pWifiIfaceStat,
808 struct sk_buff *vendor_event)
809{
810 int i = 0;
811 struct nlattr *wmmInfo;
812 if (FALSE == put_wifi_interface_info(
813 &pWifiIfaceStat->info,
814 vendor_event))
815 {
816 hddLog(VOS_TRACE_LEVEL_ERROR,
817 FL("QCA_WLAN_VENDOR_ATTR put fail") );
818 return FALSE;
819
820 }
821
822 if (nla_put_u32(vendor_event,
823 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX,
824 pWifiIfaceStat->beaconRx) ||
825 nla_put_u32(vendor_event,
826 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX,
827 pWifiIfaceStat->mgmtRx) ||
828 nla_put_u32(vendor_event,
829 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX,
830 pWifiIfaceStat->mgmtActionRx) ||
831 nla_put_u32(vendor_event,
832 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX,
833 pWifiIfaceStat->mgmtActionTx) ||
834 nla_put_u32(vendor_event,
835 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT,
836 pWifiIfaceStat->rssiMgmt) ||
837 nla_put_u32(vendor_event,
838 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA,
839 pWifiIfaceStat->rssiData) ||
840 nla_put_u32(vendor_event,
841 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK,
842 pWifiIfaceStat->rssiAck))
843 {
844 hddLog(VOS_TRACE_LEVEL_ERROR,
845 FL("QCA_WLAN_VENDOR_ATTR put fail"));
846 return FALSE;
847 }
848
849 wmmInfo = nla_nest_start(vendor_event,
850 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO);
851 for (i = 0; i < WIFI_AC_MAX; i++)
852 {
853 struct nlattr *wmmStats;
854 wmmStats = nla_nest_start(vendor_event, i);
855 if (FALSE == put_wifi_wmm_ac_stat(
856 &pWifiIfaceStat->AccessclassStats[i],
857 vendor_event))
858 {
859 hddLog(VOS_TRACE_LEVEL_ERROR,
860 FL("QCA_WLAN_VENDOR_ATTR put Fail"));
861 return FALSE;
862 }
863
864 nla_nest_end(vendor_event, wmmStats);
865 }
866 nla_nest_end(vendor_event, wmmInfo);
867 return TRUE;
868}
869
870static tSirWifiInterfaceMode
871 hdd_map_device_to_ll_iface_mode ( int deviceMode )
872{
873 switch (deviceMode)
874 {
875 case WLAN_HDD_INFRA_STATION:
876 return WIFI_INTERFACE_STA;
877 case WLAN_HDD_SOFTAP:
878 return WIFI_INTERFACE_SOFTAP;
879 case WLAN_HDD_P2P_CLIENT:
880 return WIFI_INTERFACE_P2P_CLIENT;
881 case WLAN_HDD_P2P_GO:
882 return WIFI_INTERFACE_P2P_GO;
883 case WLAN_HDD_IBSS:
884 return WIFI_INTERFACE_IBSS;
885 default:
886 /* Return Interface Mode as STA for all the unsupported modes */
887 return WIFI_INTERFACE_STA;
888 }
889}
890
891static v_BOOL_t hdd_get_interface_info(hdd_adapter_t *pAdapter,
892 tpSirWifiInterfaceInfo pInfo)
893{
894 v_U8_t *staMac = NULL;
895 hdd_station_ctx_t *pHddStaCtx;
896 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
897 tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
898
899 pInfo->mode = hdd_map_device_to_ll_iface_mode(pAdapter->device_mode);
900
901 vos_mem_copy(pInfo->macAddr,
902 pAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
903
904 if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
905 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
906 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)))
907 {
908 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
909 if (eConnectionState_NotConnected == pHddStaCtx->conn_info.connState)
910 {
911 pInfo->state = WIFI_DISCONNECTED;
912 }
913 if (eConnectionState_Connecting == pHddStaCtx->conn_info.connState)
914 {
915 hddLog(VOS_TRACE_LEVEL_ERROR,
916 "%s: Session ID %d, Connection is in progress", __func__,
917 pAdapter->sessionId);
918 pInfo->state = WIFI_ASSOCIATING;
919 }
920 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
921 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
922 {
923 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
924 hddLog(VOS_TRACE_LEVEL_ERROR,
925 "%s: client " MAC_ADDRESS_STR
926 " is in the middle of WPS/EAPOL exchange.", __func__,
927 MAC_ADDR_ARRAY(staMac));
928 pInfo->state = WIFI_AUTHENTICATING;
929 }
930 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
931 {
932 pInfo->state = WIFI_ASSOCIATED;
933 vos_mem_copy(pInfo->bssid,
934 &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN);
935 vos_mem_copy(pInfo->ssid,
936 pHddStaCtx->conn_info.SSID.SSID.ssId,
937 pHddStaCtx->conn_info.SSID.SSID.length);
938 //NULL Terminate the string.
939 pInfo->ssid[pHddStaCtx->conn_info.SSID.SSID.length] = 0;
940 }
941 }
942 vos_mem_copy(pInfo->countryStr,
943 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
944
945 vos_mem_copy(pInfo->apCountryStr,
946 pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
947
948 return TRUE;
949}
950
951/*
952 * hdd_link_layer_process_peer_stats () - This function is called after
953 * receiving Link Layer Peer statistics from FW.This function converts
954 * the firmware data to the NL data and sends the same to the kernel/upper
955 * layers.
956 */
957static v_VOID_t hdd_link_layer_process_peer_stats(hdd_adapter_t *pAdapter,
958 v_VOID_t *pData)
959{
960 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
961 tpSirWifiRateStat pWifiRateStat;
962 tpSirWifiPeerStat pWifiPeerStat;
963 tpSirWifiPeerInfo pWifiPeerInfo;
964 struct nlattr *peerInfo;
965 struct sk_buff *vendor_event;
966 int status, i;
967
968 status = wlan_hdd_validate_context(pHddCtx);
969 if (0 != status)
970 {
971 hddLog(VOS_TRACE_LEVEL_ERROR,
972 FL("HDD context is not valid") );
973 return;
974 }
975
976 pWifiPeerStat = (tpSirWifiPeerStat) pData;
977
978 hddLog(VOS_TRACE_LEVEL_INFO,
979 "LL_STATS_PEER_ALL : numPeers %u",
980 pWifiPeerStat->numPeers);
981 {
982 for (i = 0; i < pWifiPeerStat->numPeers; i++)
983 {
984 pWifiPeerInfo = (tpSirWifiPeerInfo)
985 ((uint8 *)pWifiPeerStat->peerInfo +
986 ( i * sizeof(tSirWifiPeerInfo)));
987
988 hddLog(VOS_TRACE_LEVEL_INFO,
989 " %d) LL_STATS Channel Stats "
990 " Peer Type %u "
991 " peerMacAddress %pM "
992 " capabilities 0x%x "
993 " numRate %u ",
994 i,
995 pWifiPeerInfo->type,
996 pWifiPeerInfo->peerMacAddress,
997 pWifiPeerInfo->capabilities,
998 pWifiPeerInfo->numRate);
999 {
1000 int j;
1001 for (j = 0; j < pWifiPeerInfo->numRate; j++)
1002 {
1003 pWifiRateStat = (tpSirWifiRateStat)
1004 ((tANI_U8 *) pWifiPeerInfo->rateStats +
1005 ( j * sizeof(tSirWifiRateStat)));
1006
1007 hddLog(VOS_TRACE_LEVEL_INFO,
1008 " peer Rate Stats "
1009 " preamble %u "
1010 " nss %u "
1011 " bw %u "
1012 " rateMcsIdx %u "
1013 " reserved %u "
1014 " bitrate %u "
1015 " txMpdu %u "
1016 " rxMpdu %u "
1017 " mpduLost %u "
1018 " retries %u "
1019 " retriesShort %u "
1020 " retriesLong %u",
1021 pWifiRateStat->rate.preamble,
1022 pWifiRateStat->rate.nss,
1023 pWifiRateStat->rate.bw,
1024 pWifiRateStat->rate.rateMcsIdx,
1025 pWifiRateStat->rate.reserved,
1026 pWifiRateStat->rate.bitrate,
1027 pWifiRateStat->txMpdu,
1028 pWifiRateStat->rxMpdu,
1029 pWifiRateStat->mpduLost,
1030 pWifiRateStat->retries,
1031 pWifiRateStat->retriesShort,
1032 pWifiRateStat->retriesLong);
1033 }
1034 }
1035 }
1036 }
1037
1038 /*
1039 * Allocate a size of 4096 for the peer stats comprising
1040 * each of size = sizeof (tSirWifiPeerInfo) + numRate *
1041 * sizeof (tSirWifiRateStat).Each field is put with an
1042 * NL attribute.The size of 4096 is considered assuming
1043 * that number of rates shall not exceed beyond 50 with
1044 * the sizeof (tSirWifiRateStat) being 32.
1045 */
1046 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1047 LL_STATS_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1048 QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX,
1049 GFP_KERNEL);
1050 if (!vendor_event)
1051 {
1052 hddLog(VOS_TRACE_LEVEL_ERROR,
1053 "%s: cfg80211_vendor_event_alloc failed",
1054 __func__);
1055 return;
1056 }
1057 if (nla_put_u32(vendor_event,
1058 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS,
1059 pWifiPeerStat->numPeers))
1060 {
1061 hddLog(VOS_TRACE_LEVEL_ERROR,
1062 "%s: QCA_WLAN_VENDOR_ATTR put fail", __func__);
1063 kfree_skb(vendor_event);
1064 return;
1065 }
1066
1067 peerInfo = nla_nest_start(vendor_event,
1068 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO);
1069
1070 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8 *)
1071 pWifiPeerStat->peerInfo);
1072
1073 for (i = 1; i <= pWifiPeerStat->numPeers; i++)
1074 {
1075 struct nlattr *peers = nla_nest_start(vendor_event, i);
1076 int numRate = pWifiPeerInfo->numRate;
1077
1078 if (FALSE == put_wifi_peer_info(
1079 pWifiPeerInfo, vendor_event))
1080 {
1081 hddLog(VOS_TRACE_LEVEL_ERROR,
1082 "%s: put_wifi_peer_info put fail", __func__);
1083 kfree_skb(vendor_event);
1084 return;
1085 }
1086
1087 pWifiPeerInfo = (tpSirWifiPeerInfo) ((uint8 *)
1088 pWifiPeerStat->peerInfo +
1089 (i * sizeof(tSirWifiPeerInfo)) +
1090 (numRate * sizeof (tSirWifiRateStat)));
1091 nla_nest_end(vendor_event, peers);
1092 }
1093 nla_nest_end(vendor_event, peerInfo);
1094 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1095}
1096
1097/*
1098 * hdd_link_layer_process_iface_stats () - This function is called after
1099 * receiving Link Layer Interface statistics from FW.This function converts
1100 * the firmware data to the NL data and sends the same to the kernel/upper
1101 * layers.
1102 */
1103static v_VOID_t hdd_link_layer_process_iface_stats(hdd_adapter_t *pAdapter,
1104 v_VOID_t *pData)
1105{
1106 tpSirWifiIfaceStat pWifiIfaceStat;
1107 struct sk_buff *vendor_event;
1108 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1109 int status;
1110
1111 status = wlan_hdd_validate_context(pHddCtx);
1112 if (0 != status)
1113 {
1114 hddLog(VOS_TRACE_LEVEL_ERROR,
1115 FL("HDD context is not valid") );
1116 return;
1117 }
1118 /*
1119 * Allocate a size of 4096 for the interface stats comprising
1120 * sizeof (tpSirWifiIfaceStat).The size of 4096 is considered
1121 * assuming that all these fit with in the limit.Please take
1122 * a call on the limit based on the data requirements on
1123 * interface statistics.
1124 */
1125 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1126 LL_STATS_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1127 QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX,
1128 GFP_KERNEL);
1129 if (!vendor_event)
1130 {
1131 hddLog(VOS_TRACE_LEVEL_ERROR,
1132 FL("cfg80211_vendor_event_alloc failed") );
1133 return;
1134 }
1135
1136 pWifiIfaceStat = (tpSirWifiIfaceStat) pData;
1137
1138 hddLog(VOS_TRACE_LEVEL_INFO,
1139 "WMI_LINK_STATS_IFACE Data");
1140
1141 hddLog(VOS_TRACE_LEVEL_INFO,
1142 "LL_STATS_IFACE: "
1143 " Mode %u "
1144 " MAC %pM "
1145 " State %u "
1146 " Roaming %u "
1147 " capabilities 0x%x "
1148 " SSID %s "
1149 " BSSID %pM",
1150 pWifiIfaceStat->info.mode,
1151 pWifiIfaceStat->info.macAddr,
1152 pWifiIfaceStat->info.state,
1153 pWifiIfaceStat->info.roaming,
1154 pWifiIfaceStat->info.capabilities,
1155 pWifiIfaceStat->info.ssid,
1156 pWifiIfaceStat->info.bssid);
1157
1158 hddLog(VOS_TRACE_LEVEL_INFO,
1159 " AP country str: %c%c%c",
1160 pWifiIfaceStat->info.apCountryStr[0],
1161 pWifiIfaceStat->info.apCountryStr[1],
1162 pWifiIfaceStat->info.apCountryStr[2]);
1163
1164
1165 hddLog(VOS_TRACE_LEVEL_INFO,
1166 " Country Str Association: %c%c%c",
1167 pWifiIfaceStat->info.countryStr[0],
1168 pWifiIfaceStat->info.countryStr[1],
1169 pWifiIfaceStat->info.countryStr[2]);
1170
1171 hddLog(VOS_TRACE_LEVEL_INFO,
1172 " beaconRx %u "
1173 " mgmtRx %u "
1174 " mgmtActionRx %u "
1175 " mgmtActionTx %u "
1176 " rssiMgmt %u "
1177 " rssiData %u "
1178 " rssiAck %u",
1179 pWifiIfaceStat->beaconRx,
1180 pWifiIfaceStat->mgmtRx,
1181 pWifiIfaceStat->mgmtActionRx,
1182 pWifiIfaceStat->mgmtActionTx,
1183 pWifiIfaceStat->rssiMgmt,
1184 pWifiIfaceStat->rssiData,
1185 pWifiIfaceStat->rssiAck );
1186
1187
1188 {
1189 int i;
1190 for (i = 0 ; i < WIFI_AC_MAX; i ++)
1191 {
1192 hddLog(VOS_TRACE_LEVEL_INFO,
1193
1194 " %d) LL_STATS IFACE: "
1195 " ac: %u txMpdu: %u "
1196 " rxMpdu: %u txMcast: %u "
1197 " rxMcast: %u rxAmpdu: %u "
1198 " txAmpdu: %u mpduLost: %u "
1199 " retries: %u retriesShort: %u "
1200 " retriesLong: %u contentionTimeMin: %u "
1201 " contentionTimeMax: %u contentionTimeAvg: %u "
1202 " contentionNumSamples: %u",
1203 i,
1204 pWifiIfaceStat->AccessclassStats[i].ac,
1205 pWifiIfaceStat->AccessclassStats[i].txMpdu,
1206 pWifiIfaceStat->AccessclassStats[i].rxMpdu,
1207 pWifiIfaceStat->AccessclassStats[i].txMcast,
1208 pWifiIfaceStat->AccessclassStats[i].rxMcast,
1209 pWifiIfaceStat->AccessclassStats[i].rxAmpdu,
1210 pWifiIfaceStat->AccessclassStats[i].txAmpdu,
1211 pWifiIfaceStat->AccessclassStats[i].mpduLost,
1212 pWifiIfaceStat->AccessclassStats[i].retries,
1213 pWifiIfaceStat->
1214 AccessclassStats[i].retriesShort,
1215 pWifiIfaceStat->AccessclassStats[i].retriesLong,
1216 pWifiIfaceStat->
1217 AccessclassStats[i].contentionTimeMin,
1218 pWifiIfaceStat->
1219 AccessclassStats[i].contentionTimeMax,
1220 pWifiIfaceStat->
1221 AccessclassStats[i].contentionTimeAvg,
1222 pWifiIfaceStat->
1223 AccessclassStats[i].contentionNumSamples);
1224
1225 }
1226 }
1227
1228 if (FALSE == hdd_get_interface_info( pAdapter,
1229 &pWifiIfaceStat->info))
1230 {
1231 hddLog(VOS_TRACE_LEVEL_ERROR,
1232 FL("hdd_get_interface_info get fail") );
1233 kfree_skb(vendor_event);
1234 return;
1235 }
1236
1237 if (FALSE == put_wifi_iface_stats( pWifiIfaceStat,
1238 vendor_event))
1239 {
1240 hddLog(VOS_TRACE_LEVEL_ERROR,
1241 FL("put_wifi_iface_stats fail") );
1242 kfree_skb(vendor_event);
1243 return;
1244 }
1245 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1246}
1247
1248/*
1249 * hdd_link_layer_process_radio_stats () - This function is called after
1250 * receiving Link Layer Radio statistics from FW.This function converts
1251 * the firmware data to the NL data and sends the same to the kernel/upper
1252 * layers.
1253 */
1254static v_VOID_t hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter,
1255 v_VOID_t *pData)
1256{
1257 int status, i;
1258 tpSirWifiRadioStat pWifiRadioStat;
1259 tpSirWifiChannelStats pWifiChannelStats;
1260 struct sk_buff *vendor_event;
1261 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1262 struct nlattr *chList;
1263
1264 status = wlan_hdd_validate_context(pHddCtx);
1265 if (0 != status)
1266 {
1267 hddLog(VOS_TRACE_LEVEL_ERROR,
1268 FL("HDD context is not valid") );
1269 return;
1270 }
1271 pWifiRadioStat = (tpSirWifiRadioStat) pData;
1272
1273 hddLog(VOS_TRACE_LEVEL_INFO,
1274 "LL_STATS_RADIO"
1275 " radio is %d onTime is %u "
1276 " txTime is %u rxTime is %u "
1277 " onTimeScan is %u onTimeNbd is %u "
Dino Mycle6fb96c12014-06-10 11:52:40 +05301278 " onTimeEXTScan is %u onTimeRoamScan is %u "
Sunil Duttc69bccb2014-05-26 21:30:20 +05301279 " onTimePnoScan is %u onTimeHs20 is %u "
1280 " numChannels is %u",
1281 pWifiRadioStat->radio, pWifiRadioStat->onTime,
1282 pWifiRadioStat->txTime, pWifiRadioStat->rxTime,
1283 pWifiRadioStat->onTimeScan, pWifiRadioStat->onTimeNbd,
Dino Mycle6fb96c12014-06-10 11:52:40 +05301284 pWifiRadioStat->onTimeEXTScan,
Sunil Duttc69bccb2014-05-26 21:30:20 +05301285 pWifiRadioStat->onTimeRoamScan,
1286 pWifiRadioStat->onTimePnoScan,
1287 pWifiRadioStat->onTimeHs20,
1288 pWifiRadioStat->numChannels);
1289 /*
1290 * Allocate a size of 4096 for the Radio stats comprising
1291 * sizeof (tSirWifiRadioStat) + numChannels * sizeof
1292 * (tSirWifiChannelStats).Each channel data is put with an
1293 * NL attribute.The size of 4096 is considered assuming that
1294 * number of channels shall not exceed beyond 60 with the
1295 * sizeof (tSirWifiChannelStats) being 24 bytes.
1296 */
1297
1298 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1299 LL_STATS_EVENT_BUF_SIZE + NLMSG_HDRLEN ,
1300 QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX,
1301 GFP_KERNEL);
1302
1303 if (!vendor_event)
1304 {
1305 hddLog(VOS_TRACE_LEVEL_ERROR,
1306 FL("cfg80211_vendor_event_alloc failed") );
1307 return;
1308 }
1309
1310 if (nla_put_u32(vendor_event,
1311 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID,
1312 pWifiRadioStat->radio) ||
1313 nla_put_u32(vendor_event,
1314 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME,
1315 pWifiRadioStat->onTime) ||
1316 nla_put_u32(vendor_event,
1317 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME,
1318 pWifiRadioStat->txTime) ||
1319 nla_put_u32(vendor_event,
1320 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME,
1321 pWifiRadioStat->rxTime) ||
1322 nla_put_u32(vendor_event,
1323 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN,
1324 pWifiRadioStat->onTimeScan) ||
1325 nla_put_u32(vendor_event,
1326 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD,
1327 pWifiRadioStat->onTimeNbd) ||
1328 nla_put_u32(vendor_event,
Dino Mycle6fb96c12014-06-10 11:52:40 +05301329 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_EXTSCAN,
1330 pWifiRadioStat->onTimeEXTScan)||
Sunil Duttc69bccb2014-05-26 21:30:20 +05301331 nla_put_u32(vendor_event,
1332 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN,
1333 pWifiRadioStat->onTimeRoamScan) ||
1334 nla_put_u32(vendor_event,
1335 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN,
1336 pWifiRadioStat->onTimePnoScan) ||
1337 nla_put_u32(vendor_event,
1338 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20,
1339 pWifiRadioStat->onTimeHs20) ||
1340 nla_put_u32(vendor_event,
1341 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS,
1342 pWifiRadioStat->numChannels))
1343 {
1344 hddLog(VOS_TRACE_LEVEL_ERROR,
1345 FL("QCA_WLAN_VENDOR_ATTR put fail"));
1346 kfree_skb(vendor_event);
1347 return ;
1348 }
1349
1350 chList = nla_nest_start(vendor_event,
1351 QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO);
1352 for (i = 0; i < pWifiRadioStat->numChannels; i++)
1353 {
1354 struct nlattr *chInfo;
1355
1356 pWifiChannelStats = (tpSirWifiChannelStats) ((uint8*)
1357 pWifiRadioStat->channels +
1358 (i * sizeof(tSirWifiChannelStats)));
1359
1360 hddLog(VOS_TRACE_LEVEL_INFO,
1361 " %d) Channel Info"
1362 " width is %u "
1363 " CenterFreq %u "
1364 " CenterFreq0 %u "
1365 " CenterFreq1 %u "
1366 " onTime %u "
1367 " ccaBusyTime %u",
1368 i,
1369 pWifiChannelStats->channel.width,
1370 pWifiChannelStats->channel.centerFreq,
1371 pWifiChannelStats->channel.centerFreq0,
1372 pWifiChannelStats->channel.centerFreq1,
1373 pWifiChannelStats->onTime,
1374 pWifiChannelStats->ccaBusyTime);
1375
1376
1377 chInfo = nla_nest_start(vendor_event, i);
1378
1379 if (nla_put_u32(vendor_event,
1380 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH,
1381 pWifiChannelStats->channel.width) ||
1382 nla_put_u32(vendor_event,
1383 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ,
1384 pWifiChannelStats->channel.centerFreq) ||
1385 nla_put_u32(vendor_event,
1386 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0,
1387 pWifiChannelStats->channel.centerFreq0) ||
1388 nla_put_u32(vendor_event,
1389 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1,
1390 pWifiChannelStats->channel.centerFreq1) ||
1391 nla_put_u32(vendor_event,
1392 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME,
1393 pWifiChannelStats->onTime) ||
1394 nla_put_u32(vendor_event,
1395 QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME,
1396 pWifiChannelStats->ccaBusyTime))
1397 {
1398 hddLog(VOS_TRACE_LEVEL_ERROR,
1399 FL("cfg80211_vendor_event_alloc failed") );
1400 kfree_skb(vendor_event);
1401 return ;
1402 }
1403 nla_nest_end(vendor_event, chInfo);
1404 }
1405 nla_nest_end(vendor_event, chList);
1406
1407 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1408 return;
1409}
1410
1411/*
1412 * hdd_link_layer_stats_ind_callback () - This function is called after
1413 * receiving Link Layer indications from FW.This callback converts the firmware
1414 * data to the NL data and send the same to the kernel/upper layers.
1415 */
1416static void hdd_link_layer_stats_ind_callback ( void *pCtx,
1417 int indType,
1418 void *pRsp )
1419{
1420 hdd_adapter_t *pAdapter = (hdd_adapter_t *)pCtx;
1421 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1422 int status;
1423
1424 status = wlan_hdd_validate_context(pHddCtx);
1425
1426 if (0 != status)
1427 {
1428 hddLog(VOS_TRACE_LEVEL_ERROR,
1429 FL("HDD context is not valid"));
1430 return;
1431 }
1432
1433 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1434 "%s: Link Layer Indication indType: %d", __func__, indType);
1435 switch (indType)
1436 {
1437 case SIR_HAL_LL_STATS_RESULTS_RSP:
1438 {
1439 tpSirLLStatsResults linkLayerStatsResults =
1440 (tpSirLLStatsResults)pRsp;
1441
1442
1443 hddLog(VOS_TRACE_LEVEL_INFO,
1444 FL("RESPONSE SIR_HAL_LL_STATS_RESULTS_RSP") );
1445 hddLog(VOS_TRACE_LEVEL_INFO,
1446 "LL_STATS RESULTS RESPONSE paramID = 0x%x",
1447 linkLayerStatsResults->paramId);
1448 hddLog(VOS_TRACE_LEVEL_INFO,
1449 "LL_STATS RESULTS RESPONSE ifaceId = %u",
1450 linkLayerStatsResults->ifaceId);
1451 hddLog(VOS_TRACE_LEVEL_INFO,
1452 "LL_STATS RESULTS RESPONSE respId = %u",
1453 linkLayerStatsResults->respId);
1454 hddLog(VOS_TRACE_LEVEL_INFO,
1455 "LL_STATS RESULTS RESPONSE moreResultToFollow = %u",
1456 linkLayerStatsResults->moreResultToFollow);
1457 hddLog(VOS_TRACE_LEVEL_INFO,
1458 "LL_STATS RESULTS RESPONSE result = %p",
1459 linkLayerStatsResults->result);
1460 if ( linkLayerStatsResults->paramId & WMI_LINK_STATS_RADIO )
1461 {
1462 hdd_link_layer_process_radio_stats(pAdapter,
1463 (v_VOID_t *)linkLayerStatsResults->result);
1464 }
1465 else if ( linkLayerStatsResults->paramId & WMI_LINK_STATS_IFACE )
1466 {
1467 hdd_link_layer_process_iface_stats(pAdapter,
1468 (v_VOID_t *)linkLayerStatsResults->result);
1469 }
1470 else if ( linkLayerStatsResults->paramId &
1471 WMI_LINK_STATS_ALL_PEER )
1472 {
1473 hdd_link_layer_process_peer_stats(pAdapter,
1474 (v_VOID_t *)linkLayerStatsResults->result);
1475 } /* WMI_LINK_STATS_ALL_PEER */
1476 else
1477 {
1478 hddLog(VOS_TRACE_LEVEL_ERROR,
1479 FL("INVALID LL_STATS_NOTIFY RESPONSE ***********"));
1480 }
1481
1482 break;
1483 }
1484 default:
1485 hddLog(VOS_TRACE_LEVEL_ERROR, "invalid event type %d", indType);
1486 break;
1487 }
1488 return;
1489}
1490
1491const struct
1492nla_policy
1493qca_wlan_vendor_ll_set_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX +1] =
1494{
1495 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD] =
1496 { .type = NLA_U32 },
1497 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING] =
1498 { .type = NLA_U32 },
1499};
1500
1501static int wlan_hdd_cfg80211_ll_stats_set(struct wiphy *wiphy,
1502 struct wireless_dev *wdev,
1503 void *data,
1504 int data_len)
1505{
1506 int status;
1507 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX + 1];
Dino Mycledf0a5d92014-07-04 09:41:55 +05301508 tSirLLStatsSetReq linkLayerStatsSetReq;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301509 struct net_device *dev = wdev->netdev;
1510 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1511 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1512
1513 status = wlan_hdd_validate_context(pHddCtx);
1514 if (0 != status)
1515 {
1516 hddLog(VOS_TRACE_LEVEL_ERROR,
1517 FL("HDD context is not valid"));
1518 return -EINVAL;
1519 }
1520
1521 if (NULL == pAdapter)
1522 {
1523 hddLog(VOS_TRACE_LEVEL_ERROR,
1524 FL("HDD adapter is Null"));
1525 return -ENODEV;
1526 }
Dino Mycledf0a5d92014-07-04 09:41:55 +05301527 /* check the LLStats Capability */
1528 if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
1529 (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
1530 {
1531 hddLog(VOS_TRACE_LEVEL_ERROR,
1532 FL("Link Layer Statistics not supported by Firmware"));
1533 return -EINVAL;
1534 }
Sunil Duttc69bccb2014-05-26 21:30:20 +05301535
1536 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX,
1537 (struct nlattr *)data,
1538 data_len, qca_wlan_vendor_ll_set_policy))
1539 {
1540 hddLog(VOS_TRACE_LEVEL_ERROR, FL() );
1541 return -EINVAL;
1542 }
1543 if (!tb_vendor
1544 [QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD])
1545 {
1546 hddLog(VOS_TRACE_LEVEL_ERROR, FL("MPDU size Not present"));
1547 return -EINVAL;
1548 }
1549 if (!tb_vendor[
1550 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING])
1551 {
1552 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Stats Gathering Not Present"));
1553 return -EINVAL;
1554 }
Sunil Duttc69bccb2014-05-26 21:30:20 +05301555 // Shall take the request Id if the Upper layers pass. 1 For now.
Dino Mycledf0a5d92014-07-04 09:41:55 +05301556 linkLayerStatsSetReq.reqId = 1;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301557
Dino Mycledf0a5d92014-07-04 09:41:55 +05301558 linkLayerStatsSetReq.mpduSizeThreshold =
Sunil Duttc69bccb2014-05-26 21:30:20 +05301559 nla_get_u32(
1560 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD]);
1561
Dino Mycledf0a5d92014-07-04 09:41:55 +05301562 linkLayerStatsSetReq.aggressiveStatisticsGathering =
Sunil Duttc69bccb2014-05-26 21:30:20 +05301563 nla_get_u32(
1564 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING]);
1565
1566 /* staId 0 in Firmware is reserved for Broadcast/Multicast data.
1567 * Hence the interface staId start from 1. Hence the staId matching the
1568 * interface in the firmware is sessionId + 1.
1569 */
Dino Mycledf0a5d92014-07-04 09:41:55 +05301570 linkLayerStatsSetReq.staId = pAdapter->sessionId + 1;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301571
1572
1573 hddLog(VOS_TRACE_LEVEL_INFO,
1574 "LL_STATS_SET reqId = %d",
Dino Mycledf0a5d92014-07-04 09:41:55 +05301575 linkLayerStatsSetReq.reqId);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301576 hddLog(VOS_TRACE_LEVEL_INFO,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301577 "LL_STATS_SET staId = %d", linkLayerStatsSetReq.staId);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301578 hddLog(VOS_TRACE_LEVEL_INFO,
1579 "LL_STATS_SET mpduSizeThreshold = %d",
Dino Mycledf0a5d92014-07-04 09:41:55 +05301580 linkLayerStatsSetReq.mpduSizeThreshold);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301581 hddLog(VOS_TRACE_LEVEL_INFO,
1582 "LL_STATS_SET aggressive Statistics Gathering = %d",
Dino Mycledf0a5d92014-07-04 09:41:55 +05301583 linkLayerStatsSetReq.aggressiveStatisticsGathering);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301584
1585 if (eHAL_STATUS_SUCCESS != sme_SetLinkLayerStatsIndCB(
1586 pHddCtx->hHal,
1587 pAdapter->sessionId,
1588 hdd_link_layer_stats_ind_callback,
1589 pAdapter))
1590 {
1591 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
1592 "sme_SetLinkLayerStatsIndCB Failed", __func__);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301593 return -EINVAL;
1594
1595 }
1596 if (eHAL_STATUS_SUCCESS != sme_LLStatsSetReq( pHddCtx->hHal,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301597 &linkLayerStatsSetReq))
Sunil Duttc69bccb2014-05-26 21:30:20 +05301598 {
1599 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
1600 "sme_LLStatsSetReq Failed", __func__);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301601 return -EINVAL;
1602 }
1603
1604 pAdapter->isLinkLayerStatsSet = 1;
1605
1606 return 0;
1607}
1608
1609const struct
1610nla_policy
1611qca_wlan_vendor_ll_get_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX +1] =
1612{
1613 /* Unsigned 32bit value provided by the caller issuing the GET stats
1614 * command. When reporting
1615 * the stats results, the driver uses the same value to indicate
1616 * which GET request the results
1617 * correspond to.
1618 */
1619 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID] = { .type = NLA_U32 },
1620
1621 /* Unsigned 32bit value . bit mask to identify what statistics are
1622 requested for retrieval */
1623 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = { .type = NLA_U32 },
1624};
1625
1626static int wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
1627 struct wireless_dev *wdev,
1628 void *data,
1629 int data_len)
1630{
1631 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1632 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX + 1];
Dino Mycledf0a5d92014-07-04 09:41:55 +05301633 tSirLLStatsGetReq linkLayerStatsGetReq;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301634 struct net_device *dev = wdev->netdev;
1635 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1636 int status;
1637
1638 status = wlan_hdd_validate_context(pHddCtx);
1639 if (0 != status)
1640 {
1641 hddLog(VOS_TRACE_LEVEL_ERROR,
1642 FL("HDD context is not valid"));
1643 return -EINVAL ;
1644 }
1645
1646 if (NULL == pAdapter)
1647 {
1648 hddLog(VOS_TRACE_LEVEL_FATAL,
1649 "%s: HDD adapter is Null", __func__);
1650 return -ENODEV;
1651 }
Dino Mycledf0a5d92014-07-04 09:41:55 +05301652 /* check the LLStats Capability */
1653 if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
1654 (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
1655 {
1656 hddLog(VOS_TRACE_LEVEL_ERROR,
1657 FL("Link Layer Statistics not supported by Firmware"));
1658 return -EINVAL;
1659 }
1660
Sunil Duttc69bccb2014-05-26 21:30:20 +05301661
1662 if (!pAdapter->isLinkLayerStatsSet)
1663 {
1664 hddLog(VOS_TRACE_LEVEL_FATAL,
1665 "%s: isLinkLayerStatsSet : %d",
1666 __func__, pAdapter->isLinkLayerStatsSet);
1667 return -EINVAL;
1668 }
1669
1670 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX,
1671 (struct nlattr *)data,
1672 data_len, qca_wlan_vendor_ll_get_policy))
1673 {
1674 hddLog(VOS_TRACE_LEVEL_ERROR, FL() );
1675 return -EINVAL;
1676 }
1677
1678 if (!tb_vendor
1679 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID])
1680 {
1681 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Request Id Not present"));
1682 return -EINVAL;
1683 }
1684
1685 if (!tb_vendor
1686 [QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK])
1687 {
1688 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Req Mask Not present"));
1689 return -EINVAL;
1690 }
1691
Sunil Duttc69bccb2014-05-26 21:30:20 +05301692
Dino Mycledf0a5d92014-07-04 09:41:55 +05301693 linkLayerStatsGetReq.reqId =
Sunil Duttc69bccb2014-05-26 21:30:20 +05301694 nla_get_u32( tb_vendor[
1695 QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID]);
Dino Mycledf0a5d92014-07-04 09:41:55 +05301696 linkLayerStatsGetReq.paramIdMask =
Sunil Duttc69bccb2014-05-26 21:30:20 +05301697 nla_get_u32( tb_vendor[
1698 QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK]);
1699
1700 /* staId 0 in Firmware is reserved for Broadcast/Multicast data.
1701 * Hence the interface staId start from 1. Hence the staId matching the
1702 * interface in the firmware is sessionId + 1.
1703 */
Dino Mycledf0a5d92014-07-04 09:41:55 +05301704 linkLayerStatsGetReq.staId = pAdapter->sessionId + 1;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301705
1706 hddLog(VOS_TRACE_LEVEL_INFO,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301707 "LL_STATS_GET reqId = %d", linkLayerStatsGetReq.reqId);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301708 hddLog(VOS_TRACE_LEVEL_INFO,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301709 "LL_STATS_GET staId = %d", linkLayerStatsGetReq.staId);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301710 hddLog(VOS_TRACE_LEVEL_INFO,
1711 "LL_STATS_GET paramIdMask = %d",
Dino Mycledf0a5d92014-07-04 09:41:55 +05301712 linkLayerStatsGetReq.paramIdMask);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301713
1714 if (eHAL_STATUS_SUCCESS != sme_LLStatsGetReq( pHddCtx->hHal,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301715 &linkLayerStatsGetReq))
Sunil Duttc69bccb2014-05-26 21:30:20 +05301716 {
1717 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:"
1718 "sme_LLStatsGetReq Failed", __func__);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301719 return -EINVAL;
1720 }
1721 return 0;
1722}
1723
1724const struct
1725nla_policy
1726qca_wlan_vendor_ll_clr_policy[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX +1] =
1727{
1728 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] = {.type = NLA_U32 },
1729 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ] = {.type = NLA_U8 },
1730 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK] = {.type = NLA_U32 },
1731 [QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP] = {.type = NLA_U8 },
1732};
1733
1734static int wlan_hdd_cfg80211_ll_stats_clear(struct wiphy *wiphy,
1735 struct wireless_dev *wdev,
1736 void *data,
1737 int data_len)
1738{
1739 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1740 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
Dino Mycledf0a5d92014-07-04 09:41:55 +05301741 tSirLLStatsClearReq linkLayerStatsClearReq;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301742 struct net_device *dev = wdev->netdev;
1743 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1744 u32 statsClearReqMask;
1745 u8 stopReq;
1746 int status;
1747
1748 status = wlan_hdd_validate_context(pHddCtx);
1749 if (0 != status)
1750 {
1751 hddLog(VOS_TRACE_LEVEL_ERROR,
1752 FL("HDD context is not valid"));
1753 return -EINVAL;
1754 }
1755
1756 if (NULL == pAdapter)
1757 {
1758 hddLog(VOS_TRACE_LEVEL_FATAL,
1759 "%s: HDD adapter is Null", __func__);
1760 return -ENODEV;
1761 }
Dino Mycledf0a5d92014-07-04 09:41:55 +05301762 /* check the LLStats Capability */
1763 if ( (TRUE != pHddCtx->cfg_ini->fEnableLLStats) ||
1764 (TRUE != sme_IsFeatureSupportedByFW(LINK_LAYER_STATS_MEAS)))
1765 {
1766 hddLog(VOS_TRACE_LEVEL_ERROR,
1767 FL("Enable LLStats Capability"));
1768 return -EINVAL;
1769 }
Sunil Duttc69bccb2014-05-26 21:30:20 +05301770
1771 if (!pAdapter->isLinkLayerStatsSet)
1772 {
1773 hddLog(VOS_TRACE_LEVEL_FATAL,
1774 "%s: isLinkLayerStatsSet : %d",
1775 __func__, pAdapter->isLinkLayerStatsSet);
1776 return -EINVAL;
1777 }
1778
1779 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
1780 (struct nlattr *)data,
1781 data_len, qca_wlan_vendor_ll_clr_policy))
1782 {
1783 hddLog(VOS_TRACE_LEVEL_ERROR, FL() );
1784 return -EINVAL;
1785 }
1786
1787 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK] ||
1788
1789 !tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ])
1790 {
1791 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Error in LL_STATS CLR CONFIG PARA") );
1792 return -EINVAL;
1793
1794 }
1795
Sunil Duttc69bccb2014-05-26 21:30:20 +05301796
Dino Mycledf0a5d92014-07-04 09:41:55 +05301797 statsClearReqMask = linkLayerStatsClearReq.statsClearReqMask =
Sunil Duttc69bccb2014-05-26 21:30:20 +05301798 nla_get_u32(
1799 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK]);
1800
Dino Mycledf0a5d92014-07-04 09:41:55 +05301801 stopReq = linkLayerStatsClearReq.stopReq =
Sunil Duttc69bccb2014-05-26 21:30:20 +05301802 nla_get_u8(
1803 tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ]);
1804
1805 // Shall take the request Id if the Upper layers pass. 1 For now.
Dino Mycledf0a5d92014-07-04 09:41:55 +05301806 linkLayerStatsClearReq.reqId = 1;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301807
1808 /* staId 0 in Firmware is reserved for Broadcast/Multicast data.
1809 * Hence the interface staId start from 1. Hence the staId matching the
1810 * interface in the firmware is sessionId + 1.
1811 */
Dino Mycledf0a5d92014-07-04 09:41:55 +05301812 linkLayerStatsClearReq.staId = pAdapter->sessionId + 1;
Sunil Duttc69bccb2014-05-26 21:30:20 +05301813
1814 hddLog(VOS_TRACE_LEVEL_INFO,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301815 "LL_STATS_CLEAR reqId = %d", linkLayerStatsClearReq.reqId);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301816 hddLog(VOS_TRACE_LEVEL_INFO,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301817 "LL_STATS_CLEAR staId = %d", linkLayerStatsClearReq.staId);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301818 hddLog(VOS_TRACE_LEVEL_INFO,
1819 "LL_STATS_CLEAR statsClearReqMask = 0x%X",
Dino Mycledf0a5d92014-07-04 09:41:55 +05301820 linkLayerStatsClearReq.statsClearReqMask);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301821 hddLog(VOS_TRACE_LEVEL_INFO,
1822 "LL_STATS_CLEAR stopReq = %d",
Dino Mycledf0a5d92014-07-04 09:41:55 +05301823 linkLayerStatsClearReq.stopReq);
Sunil Duttc69bccb2014-05-26 21:30:20 +05301824
1825 if (eHAL_STATUS_SUCCESS == sme_LLStatsClearReq(pHddCtx->hHal,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301826 &linkLayerStatsClearReq))
Sunil Duttc69bccb2014-05-26 21:30:20 +05301827 {
1828 struct sk_buff *temp_skbuff;
1829 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1830 2 * sizeof(u32) +
1831 NLMSG_HDRLEN);
1832
1833 if (temp_skbuff != NULL)
1834 {
1835
1836 if (nla_put_u32(temp_skbuff,
1837 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK,
1838 statsClearReqMask) ||
1839 nla_put_u32(temp_skbuff,
1840 QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP,
1841 stopReq))
1842 {
1843 hddLog(VOS_TRACE_LEVEL_ERROR, FL("LL_STATS_CLR put fail"));
1844 kfree_skb(temp_skbuff);
1845 return -EINVAL;
1846 }
1847 /* If the ask is to stop the stats collection as part of clear
1848 * (stopReq = 1) , ensure that no further requests of get
1849 * go to the firmware by having isLinkLayerStatsSet set to 0.
1850 * However it the stopReq as part of the clear request is 0 ,
Dino Mycledf0a5d92014-07-04 09:41:55 +05301851 * the request to get the statistics are honoured as in this
Sunil Duttc69bccb2014-05-26 21:30:20 +05301852 * case the firmware is just asked to clear the statistics.
1853 */
Dino Mycledf0a5d92014-07-04 09:41:55 +05301854 if (linkLayerStatsClearReq.stopReq == 1)
Sunil Duttc69bccb2014-05-26 21:30:20 +05301855 pAdapter->isLinkLayerStatsSet = 0;
1856 return cfg80211_vendor_cmd_reply(temp_skbuff);
1857 }
1858 return -ENOMEM;
1859 }
Sunil Duttc69bccb2014-05-26 21:30:20 +05301860 return -EINVAL;
1861}
1862#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1863
Dino Mycle6fb96c12014-06-10 11:52:40 +05301864#ifdef WLAN_FEATURE_EXTSCAN
1865static const struct nla_policy
1866wlan_hdd_extscan_config_policy
1867 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] =
1868{
1869 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] =
1870 { .type = NLA_U32 },
1871 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] =
1872 { .type = NLA_U32 },
1873 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 },
1874 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] =
1875 { .type = NLA_U32 },
1876 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = { .type = NLA_U8 },
1877 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = { .type = NLA_U8 },
1878
1879 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = { .type = NLA_U8 },
1880 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = { .type = NLA_U8 },
1881 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = { .type = NLA_U32 },
1882 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] =
1883 { .type = NLA_U8 },
1884 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] =
1885 { .type = NLA_U32 },
1886 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] =
1887 { .type = NLA_U32 },
1888 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] =
1889 { .type = NLA_U32 },
1890 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD] =
1891 { .type = NLA_U8 },
1892 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] =
1893 { .type = NLA_U8 },
1894 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] =
1895 { .type = NLA_U8 },
1896
1897 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] =
1898 { .type = NLA_U32 },
1899 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] =
1900 { .type = NLA_UNSPEC },
1901 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] =
1902 { .type = NLA_S32 },
1903 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] =
1904 { .type = NLA_S32 },
1905 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] =
1906 { .type = NLA_U32 },
1907 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] =
1908 { .type = NLA_U32 },
1909 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] =
1910 { .type = NLA_U32 },
1911 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]
1912 = { .type = NLA_U32 },
1913 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] =
1914 { .type = NLA_U32 },
1915 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type =
1916 NLA_U32 },
1917};
1918
1919static void wlan_hdd_cfg80211_extscan_get_capabilities_ind(void *ctx, void *pMsg)
1920{
1921 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
1922 struct sk_buff *skb = NULL;
1923 tpSirEXTScanCapabilitiesEvent pData =
1924 (tpSirEXTScanCapabilitiesEvent) pMsg;
1925
1926 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
1927 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
1928 "or pData(%p) is null"), pData);
1929 return;
1930 }
1931
1932 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1933 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1934 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX,
1935 GFP_KERNEL);
1936
1937 if (!skb) {
1938 hddLog(VOS_TRACE_LEVEL_ERROR,
1939 FL("cfg80211_vendor_event_alloc failed"));
1940 return;
1941 }
1942
1943 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
1944 hddLog(VOS_TRACE_LEVEL_INFO, "Scan cache size (%u)", pData->scanCacheSize);
1945 hddLog(VOS_TRACE_LEVEL_INFO, "Scan buckets (%u)", pData->scanBuckets);
1946 hddLog(VOS_TRACE_LEVEL_INFO, "Max AP per scan (%u)", pData->maxApPerScan);
1947 hddLog(VOS_TRACE_LEVEL_INFO, "maxRssiSampleSize (%u)",
1948 pData->maxRssiSampleSize);
1949 hddLog(VOS_TRACE_LEVEL_INFO, "maxScanReportingThreshold (%u)",
1950 pData->maxScanReportingThreshold);
1951 hddLog(VOS_TRACE_LEVEL_INFO, "maxHotlistAPs (%u)", pData->maxHotlistAPs);
1952 hddLog(VOS_TRACE_LEVEL_INFO, "maxSignificantWifiChangeAPs (%u)",
1953 pData->maxSignificantWifiChangeAPs);
1954 hddLog(VOS_TRACE_LEVEL_INFO, "maxBsidHistoryEntries (%u)",
1955 pData->maxBsidHistoryEntries);
1956
1957 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1958 pData->requestId) ||
1959 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status) ||
1960 nla_put_u32(skb,
1961 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE,
1962 pData->scanCacheSize) ||
1963 nla_put_u32(skb,
1964 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS,
1965 pData->scanBuckets) ||
1966 nla_put_u32(skb,
1967 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN,
1968 pData->maxApPerScan) ||
1969 nla_put_u32(skb,
1970 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE,
1971 pData->maxRssiSampleSize) ||
1972 nla_put_u32(skb,
1973 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD,
1974 pData->maxScanReportingThreshold) ||
1975 nla_put_u32(skb,
1976 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_APS,
1977 pData->maxHotlistAPs) ||
1978 nla_put_u32(skb,
1979 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1980 pData->maxSignificantWifiChangeAPs) ||
1981 nla_put_u32(skb,
1982 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES,
1983 pData->maxBsidHistoryEntries)) {
1984 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
1985 goto nla_put_failure;
1986 }
1987
1988 cfg80211_vendor_event(skb, GFP_KERNEL);
1989 return;
1990
1991nla_put_failure:
1992 kfree_skb(skb);
1993 return;
1994}
1995
1996
1997static void wlan_hdd_cfg80211_extscan_start_rsp(void *ctx, void *pMsg)
1998{
1999 tpSirEXTScanStartRspParams pData = (tpSirEXTScanStartRspParams) pMsg;
2000 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2001 struct sk_buff *skb = NULL;
2002 tpAniSirGlobal pMac = PMAC_STRUCT( pHddCtx->hHal );
2003
2004
2005 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2006 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2007 "or pData(%p) is null"), pData);
2008 return;
2009 }
2010
2011 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2012 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2013 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX,
2014 GFP_KERNEL);
2015
2016 if (!skb) {
2017 hddLog(VOS_TRACE_LEVEL_ERROR,
2018 FL("cfg80211_vendor_event_alloc failed"));
2019 return;
2020 }
2021 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2022 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2023 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2024
2025 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2026 pData->requestId) ||
2027 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2028 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2029 goto nla_put_failure;
2030 }
2031
2032 /*
2033 * Store the Request ID for comparing with the requestID obtained
2034 * in other requests.HDD shall return a failure is the extscan_stop
2035 * request is issued with a different requestId as that of the
2036 * extscan_start request. Also, This requestId shall be used while
2037 * indicating the full scan results to the upper layers.
2038 * The requestId is stored with the assumption that the firmware
2039 * shall return the ext scan start request's requestId in ext scan
2040 * start response.
2041 */
2042 if (pData->status == 0)
2043 pMac->sme.extScanStartReqId = pData->requestId;
2044
2045
2046 cfg80211_vendor_event(skb, GFP_KERNEL);
2047 return;
2048
2049nla_put_failure:
2050 kfree_skb(skb);
2051 return;
2052}
2053
2054
2055static void wlan_hdd_cfg80211_extscan_stop_rsp(void *ctx, void *pMsg)
2056{
2057 tpSirEXTScanStopRspParams pData = (tpSirEXTScanStopRspParams) pMsg;
2058 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2059 struct sk_buff *skb = NULL;
2060
2061 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2062 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2063 "or pData(%p) is null"), pData);
2064 return;
2065 }
2066
2067 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2068 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2069 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX,
2070 GFP_KERNEL);
2071
2072 if (!skb) {
2073 hddLog(VOS_TRACE_LEVEL_ERROR,
2074 FL("cfg80211_vendor_event_alloc failed"));
2075 return;
2076 }
2077 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2078 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2079
2080 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2081 pData->requestId) ||
2082 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2083 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2084 goto nla_put_failure;
2085 }
2086
2087 cfg80211_vendor_event(skb, GFP_KERNEL);
2088 return;
2089
2090nla_put_failure:
2091 kfree_skb(skb);
2092 return;
2093}
2094
2095
2096static void wlan_hdd_cfg80211_extscan_set_bss_hotlist_rsp(void *ctx,
2097 void *pMsg)
2098{
2099 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2100 struct sk_buff *skb = NULL;
2101 tpSirEXTScanSetBssidHotListRspParams pData =
2102 (tpSirEXTScanSetBssidHotListRspParams) pMsg;
2103
2104 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2105 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2106 "or pData(%p) is null"), pData);
2107 return;
2108 }
2109 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2110 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2111 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX,
2112 GFP_KERNEL);
2113
2114 if (!skb) {
2115 hddLog(VOS_TRACE_LEVEL_ERROR,
2116 FL("cfg80211_vendor_event_alloc failed"));
2117 return;
2118 }
2119 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2120 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2121 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2122
2123 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2124 pData->requestId) ||
2125 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2126 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2127 goto nla_put_failure;
2128 }
2129
2130 cfg80211_vendor_event(skb, GFP_KERNEL);
2131 return;
2132
2133nla_put_failure:
2134 kfree_skb(skb);
2135 return;
2136}
2137
2138static void wlan_hdd_cfg80211_extscan_reset_bss_hotlist_rsp(void *ctx,
2139 void *pMsg)
2140{
2141 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2142 struct sk_buff *skb = NULL;
2143 tpSirEXTScanResetBssidHotlistRspParams pData =
2144 (tpSirEXTScanResetBssidHotlistRspParams) pMsg;
2145
2146 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2147 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2148 "or pData(%p) is null"), pData);
2149 return;
2150 }
2151
2152 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2153 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2154 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX,
2155 GFP_KERNEL);
2156
2157 if (!skb) {
2158 hddLog(VOS_TRACE_LEVEL_ERROR,
2159 FL("cfg80211_vendor_event_alloc failed"));
2160 return;
2161 }
2162 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2163 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2164
2165 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2166 pData->requestId) ||
2167 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2168 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2169 goto nla_put_failure;
2170 }
2171
2172 cfg80211_vendor_event(skb, GFP_KERNEL);
2173 return;
2174
2175nla_put_failure:
2176 kfree_skb(skb);
2177 return;
2178}
2179
2180
2181static void wlan_hdd_cfg80211_extscan_set_signf_wifi_change_rsp(void *ctx,
2182 void *pMsg)
2183{
2184 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2185 struct sk_buff *skb = NULL;
2186 tpSirEXTScanSetSignificantChangeRspParams pData =
2187 (tpSirEXTScanSetSignificantChangeRspParams) pMsg;
2188
2189 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2190 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2191 "or pData(%p) is null"), pData);
2192 return;
2193 }
2194
2195 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2196 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2197 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX,
2198 GFP_KERNEL);
2199
2200 if (!skb) {
2201 hddLog(VOS_TRACE_LEVEL_ERROR,
2202 FL("cfg80211_vendor_event_alloc failed"));
2203 return;
2204 }
2205 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2206 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2207 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2208
2209 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2210 pData->requestId) ||
2211 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2212 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2213 goto nla_put_failure;
2214 }
2215
2216 cfg80211_vendor_event(skb, GFP_KERNEL);
2217 return;
2218
2219nla_put_failure:
2220 kfree_skb(skb);
2221 return;
2222}
2223
2224
2225static void wlan_hdd_cfg80211_extscan_reset_signf_wifi_change_rsp(void *ctx,
2226 void *pMsg)
2227{
2228 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2229 struct sk_buff *skb = NULL;
2230 tpSirEXTScanResetSignificantChangeRspParams pData =
2231 (tpSirEXTScanResetSignificantChangeRspParams) pMsg;
2232
2233 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2234 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2235 "or pData(%p) is null"), pData);
2236 return;
2237 }
2238
2239 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2240 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2241 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX,
2242 GFP_KERNEL);
2243
2244 if (!skb) {
2245 hddLog(VOS_TRACE_LEVEL_ERROR,
2246 FL("cfg80211_vendor_event_alloc failed"));
2247 return;
2248 }
2249 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2250 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2251 hddLog(VOS_TRACE_LEVEL_INFO, "Status (%u)", pData->status);
2252
2253 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2254 pData->requestId) ||
2255 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS, pData->status)) {
2256 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2257 goto nla_put_failure;
2258 }
2259
2260 cfg80211_vendor_event(skb, GFP_KERNEL);
2261 return;
2262
2263nla_put_failure:
2264 kfree_skb(skb);
2265 return;
2266}
2267
2268static void wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
2269 void *pMsg)
2270{
2271 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2272 struct sk_buff *skb = NULL;
2273 tANI_U32 i = 0, j, resultsPerEvent;
2274 tANI_S32 totalResults;
2275 tpSirWifiScanResultEvent pData = (tpSirWifiScanResultEvent) pMsg;
2276 tpSirWifiScanResult pSirWifiScanResult;
2277
2278 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2279 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2280 "or pData(%p) is null"), pData);
2281 return;
2282 }
2283 totalResults = pData->numOfAps;
2284 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2285 hddLog(VOS_TRACE_LEVEL_INFO, "Num results (%u)", pData->numOfAps);
2286 hddLog(VOS_TRACE_LEVEL_INFO, "More Data (%u)", pData->moreData);
2287
2288 do{
2289 resultsPerEvent = ((totalResults >= EXTSCAN_MAX_CACHED_RESULTS_PER_IND) ?
2290 EXTSCAN_MAX_CACHED_RESULTS_PER_IND : totalResults);
2291 totalResults -= EXTSCAN_MAX_CACHED_RESULTS_PER_IND;
2292
2293 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2294 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2295 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX,
2296 GFP_KERNEL);
2297
2298 if (!skb) {
2299 hddLog(VOS_TRACE_LEVEL_ERROR,
2300 FL("cfg80211_vendor_event_alloc failed"));
2301 return;
2302 }
2303
2304 hddLog(VOS_TRACE_LEVEL_INFO, "resultsPerEvent (%u)", resultsPerEvent);
2305
2306 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2307 pData->requestId) ||
2308 nla_put_u32(skb,
2309 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2310 resultsPerEvent)) {
2311 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2312 goto fail;
2313 }
2314 if (nla_put_u8(skb,
2315 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
2316 pData->moreData ? 1 : (totalResults > 0 ? 1 : 0 )))
2317 {
2318 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2319 goto fail;
2320 }
2321
2322 if (resultsPerEvent) {
2323 struct nlattr *aps;
2324
2325 aps = nla_nest_start(skb,
2326 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
2327 if (!aps)
2328 {
2329 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2330 goto fail;
2331 }
2332
2333 for (j = 0; j < resultsPerEvent; j++, i++) {
2334 struct nlattr *ap;
2335 pSirWifiScanResult = (tpSirWifiScanResult) ((tANI_U8 *)
2336 pData->ap + ( i* sizeof(tSirWifiScanResult)));
2337
2338 hddLog(VOS_TRACE_LEVEL_INFO, "[index=%u] Timestamp(%llu) "
2339 "Ssid (%s)"
2340 "Bssid: %pM "
2341 "Channel (%u)"
2342 "Rssi (%d)"
2343 "RTT (%u)"
2344 "RTT_SD (%u)",
2345 i,
2346 pSirWifiScanResult->ts,
2347 pSirWifiScanResult->ssid,
2348 pSirWifiScanResult->bssid,
2349 pSirWifiScanResult->channel,
2350 pSirWifiScanResult->rssi,
2351 pSirWifiScanResult->rtt,
2352 pSirWifiScanResult->rtt_sd);
2353
2354 ap = nla_nest_start(skb, j + 1);
2355 if (!ap)
2356 {
2357 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2358 goto fail;
2359 }
2360
2361 if (nla_put_u64(skb,
2362 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
2363 pSirWifiScanResult->ts) )
2364 {
2365 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2366 goto fail;
2367 }
2368 if (nla_put(skb,
2369 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
2370 sizeof(pSirWifiScanResult->ssid),
2371 pSirWifiScanResult->ssid) )
2372 {
2373 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2374 goto fail;
2375 }
2376 if (nla_put(skb,
2377 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
2378 sizeof(pSirWifiScanResult->bssid),
2379 pSirWifiScanResult->bssid) )
2380 {
2381 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2382 goto fail;
2383 }
2384 if (nla_put_u32(skb,
2385 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
2386 pSirWifiScanResult->channel) )
2387 {
2388 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2389 goto fail;
2390 }
2391 if (nla_put_u32(skb,
2392 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
2393 pSirWifiScanResult->rssi) )
2394 {
2395 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2396 goto fail;
2397 }
2398 if (nla_put_u32(skb,
2399 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
2400 pSirWifiScanResult->rtt) )
2401 {
2402 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2403 goto fail;
2404 }
2405 if (nla_put_u32(skb,
2406 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
2407 pSirWifiScanResult->rtt_sd))
2408 {
2409 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2410 goto fail;
2411 }
2412
2413 nla_nest_end(skb, ap);
2414 }
2415 nla_nest_end(skb, aps);
2416
2417 }
2418 cfg80211_vendor_event(skb, GFP_KERNEL);
2419 } while (totalResults > 0);
2420
2421 return;
2422fail:
2423 kfree_skb(skb);
2424 return;
2425}
2426
2427static void wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
2428 void *pMsg)
2429{
2430 tpSirWifiScanResultEvent pData = (tpSirWifiScanResultEvent) pMsg;
2431 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2432 struct sk_buff *skb = NULL;
2433 tANI_U32 i;
2434
2435 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2436 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2437 "or pData(%p) is null"), pData);
2438 return;
2439 }
2440
2441 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2442 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2443 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX,
2444 GFP_KERNEL);
2445
2446 if (!skb) {
2447 hddLog(VOS_TRACE_LEVEL_ERROR,
2448 FL("cfg80211_vendor_event_alloc failed"));
2449 return;
2450 }
2451 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2452 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2453 hddLog(VOS_TRACE_LEVEL_INFO, "Num results (%u)", pData->numOfAps);
2454 hddLog(VOS_TRACE_LEVEL_INFO, "More Data (%u)", pData->moreData);
2455
2456 for (i = 0; i < pData->numOfAps; i++) {
2457 hddLog(VOS_TRACE_LEVEL_INFO, "[index=%u] Timestamp(0x%lld) "
2458 "Ssid (%s) "
2459 "Bssid (" MAC_ADDRESS_STR ") "
2460 "Channel (%u) "
2461 "Rssi (%d) "
2462 "RTT (%u) "
2463 "RTT_SD (%u) ",
2464 i,
2465 pData->ap[i].ts,
2466 pData->ap[i].ssid,
2467 MAC_ADDR_ARRAY(pData->ap[i].bssid),
2468 pData->ap[i].channel,
2469 pData->ap[i].rssi,
2470 pData->ap[i].rtt,
2471 pData->ap[i].rtt_sd);
2472 }
2473
2474 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2475 pData->requestId) ||
2476 nla_put_u32(skb,
2477 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2478 pData->numOfAps)) {
2479 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2480 goto fail;
2481 }
2482 if (pData->numOfAps) {
2483 struct nlattr *aps;
2484
2485 aps = nla_nest_start(skb,
2486 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
2487 if (!aps)
2488 goto fail;
2489
2490 for (i = 0; i < pData->numOfAps; i++) {
2491 struct nlattr *ap;
2492
2493 ap = nla_nest_start(skb, i + 1);
2494 if (!ap)
2495 goto fail;
2496
2497 if (nla_put_u64(skb,
2498 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
2499 pData->ap[i].ts) ||
2500 nla_put(skb,
2501 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
2502 sizeof(pData->ap[i].ssid),
2503 pData->ap[i].ssid) ||
2504 nla_put(skb,
2505 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
2506 sizeof(pData->ap[i].bssid),
2507 pData->ap[i].bssid) ||
2508 nla_put_u32(skb,
2509 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
2510 pData->ap[i].channel) ||
2511 nla_put_s32(skb,
2512 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
2513 pData->ap[i].rssi) ||
2514 nla_put_u32(skb,
2515 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
2516 pData->ap[i].rtt) ||
2517 nla_put_u32(skb,
2518 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
2519 pData->ap[i].rtt_sd))
2520 goto fail;
2521
2522 nla_nest_end(skb, ap);
2523 }
2524 nla_nest_end(skb, aps);
2525
2526 if (nla_put_u8(skb,
2527 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
2528 pData->moreData))
2529 goto fail;
2530 }
2531
2532 cfg80211_vendor_event(skb, GFP_KERNEL);
2533 return;
2534
2535fail:
2536 kfree_skb(skb);
2537 return;
2538
2539}
2540static void wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(void *ctx,
2541 void *pMsg)
2542{
2543 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2544 struct sk_buff *skb = NULL;
2545 tANI_U32 i, j;
2546 tpSirWifiSignificantChangeEvent pData =
2547 (tpSirWifiSignificantChangeEvent) pMsg;
2548
2549 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2550 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2551 "or pData(%p) is null"), pData);
2552 return;
2553 }
2554 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2555 EXTSCAN_EVENT_BUF_SIZE,
2556 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
2557 GFP_KERNEL);
2558
2559 if (!skb) {
2560 hddLog(VOS_TRACE_LEVEL_ERROR,
2561 FL("cfg80211_vendor_event_alloc failed"));
2562 return;
2563 }
2564 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2565 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2566 hddLog(VOS_TRACE_LEVEL_INFO, "total List Size %u ", pData->numSigRssiBss);
2567 hddLog(VOS_TRACE_LEVEL_INFO, " CUrrent List size (%u)",
2568 pData->numSigRssiBss);
2569 hddLog(VOS_TRACE_LEVEL_INFO, "moreData (%u)", pData->moreData);
2570
2571 for (i = 0; i < pData->numSigRssiBss; i++) {
2572 hddLog(VOS_TRACE_LEVEL_INFO , "Rssi List [%d] BSSID: (%pM) Channel %u "
2573 " num RSSI %u ",
2574 i, pData->sigRssiResult[i].bssid,
2575 pData->sigRssiResult[i].channel,
2576 pData->sigRssiResult[i].numRssi);
2577
2578 for (j = 0; j < pData->sigRssiResult[i].numRssi; j++){
2579
2580 hddLog(VOS_TRACE_LEVEL_INFO,
2581 " [%d]",
2582 pData->sigRssiResult[i].rssi[0]);
2583
2584 }
2585 }
2586
2587
2588 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2589 pData->requestId) ||
2590 nla_put_u32(skb,
2591 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2592 pData->numSigRssiBss)) {
2593 hddLog(VOS_TRACE_LEVEL_ERROR, FL("put fail"));
2594 goto fail;
2595 }
2596
2597 if (pData->numSigRssiBss) {
2598 struct nlattr *aps;
2599 aps = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
2600 if (!aps)
2601 goto fail;
2602 for (i = 0; i < pData->numSigRssiBss; i++) {
2603 struct nlattr *ap;
2604
2605 ap = nla_nest_start(skb, i);
2606 if (!ap)
2607 goto fail;
2608 if (nla_put(skb,
2609 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
2610 sizeof(tSirMacAddr), pData->sigRssiResult[i].bssid) ||
2611 nla_put_u32(skb,
2612 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
2613 pData->sigRssiResult[i].channel) ||
2614 nla_put_u32(skb,
2615 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
2616 pData->sigRssiResult[i].numRssi) ||
2617 nla_put(skb,
2618 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
2619 sizeof(s32) * pData->sigRssiResult[i].numRssi,
2620 pData->sigRssiResult[i].rssi))
2621 goto fail;
2622 nla_nest_end(skb, ap);
2623 }
2624 nla_nest_end(skb, aps);
2625 if (nla_put_u8(skb,
2626 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
2627 pData->moreData))
2628 goto fail;
2629 }
2630 cfg80211_vendor_event(skb, GFP_KERNEL);
2631 return;
2632fail:
2633 kfree_skb(skb);
2634 return;
2635}
2636
2637static void wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
2638 void *pMsg)
2639{
2640 struct sk_buff *skb;
2641 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2642 tpSirWifiFullScanResultEvent pData =
2643 (tpSirWifiFullScanResultEvent) (pMsg);
2644
2645 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2646 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2647 "or pData(%p) is null"), pData);
2648 return;
2649 }
2650
2651 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2652 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2653 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
2654 GFP_KERNEL);
2655
2656 if (!skb) {
2657 hddLog(VOS_TRACE_LEVEL_ERROR,
2658 FL("cfg80211_vendor_event_alloc failed"));
2659 return;
2660 }
2661
2662 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2663 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%u)"), pData->requestId);
2664 hddLog(VOS_TRACE_LEVEL_INFO, FL("More Data (%u)"), pData->moreData);
2665 hddLog(VOS_TRACE_LEVEL_INFO, FL("AP Info: Timestamp(0x%llX) "
2666 "Ssid (%s)"
2667 "Bssid (" MAC_ADDRESS_STR ")"
2668 "Channel (%u)"
2669 "Rssi (%d)"
2670 "RTT (%u)"
2671 "RTT_SD (%u)"),
2672 pData->ap.ts,
2673 pData->ap.ssid,
2674 MAC_ADDR_ARRAY(pData->ap.bssid),
2675 pData->ap.channel,
2676 pData->ap.rssi,
2677 pData->ap.rtt,
2678 pData->ap.rtt_sd);
2679 hddLog(VOS_TRACE_LEVEL_INFO, "IE Length (%u)", pData->ieLength);
2680 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2681 pData->requestId) ||
2682 nla_put_u64(skb,
2683 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
2684 pData->ap.ts) ||
2685 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
2686 sizeof(pData->ap.ssid),
2687 pData->ap.ssid) ||
2688 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
2689 WNI_CFG_BSSID_LEN,
2690 pData->ap.bssid) ||
2691 nla_put_u32(skb,
2692 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
2693 pData->ap.channel) ||
2694 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
2695 pData->ap.rssi) ||
2696 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
2697 pData->ap.rtt) ||
2698 nla_put_u32(skb,
2699 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
2700 pData->ap.rtt_sd) ||
2701 nla_put_u16(skb,
2702 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
2703 pData->ap.beaconPeriod) ||
2704 nla_put_u16(skb,
2705 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
2706 pData->ap.capability) ||
2707 nla_put_u32(skb,
2708 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
2709 pData->ieLength))
2710 {
2711 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2712 goto nla_put_failure;
2713 }
2714 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
2715 pData->ieLength,
2716 pData->ie))
2717 {
2718 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2719 goto nla_put_failure;
2720 }
2721
2722 cfg80211_vendor_event(skb, GFP_KERNEL);
2723 return;
2724
2725nla_put_failure:
2726 kfree_skb(skb);
2727 return;
2728}
2729
2730static void wlan_hdd_cfg80211_extscan_scan_res_available_event(void *ctx,
2731 void *pMsg)
2732{
2733 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2734 struct sk_buff *skb = NULL;
2735 tpSirEXTScanResultsAvailableIndParams pData =
2736 (tpSirEXTScanResultsAvailableIndParams) pMsg;
2737
2738 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2739 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2740 "or pData(%p) is null"), pData);
2741 return;
2742 }
2743
2744 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2745 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2746 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
2747 GFP_KERNEL);
2748
2749 if (!skb) {
2750 hddLog(VOS_TRACE_LEVEL_ERROR,
2751 FL("cfg80211_vendor_event_alloc failed"));
2752 return;
2753 }
2754
2755 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2756 hddLog(VOS_TRACE_LEVEL_INFO, "Req Id (%u)", pData->requestId);
2757 hddLog(VOS_TRACE_LEVEL_INFO, "Num results (%u)",
2758 pData->numResultsAvailable);
2759 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2760 pData->requestId) ||
2761 nla_put_u32(skb,
2762 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
2763 pData->numResultsAvailable)) {
2764 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2765 goto nla_put_failure;
2766 }
2767
2768 cfg80211_vendor_event(skb, GFP_KERNEL);
2769 return;
2770
2771nla_put_failure:
2772 kfree_skb(skb);
2773 return;
2774}
2775
2776static void wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx, void *pMsg)
2777{
2778 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2779 struct sk_buff *skb = NULL;
2780 tpSirEXTScanProgressIndParams pData =
2781 (tpSirEXTScanProgressIndParams) pMsg;
2782
2783 if (wlan_hdd_validate_context(pHddCtx) || !pData) {
2784 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid "
2785 "or pData(%p) is null"), pData);
2786 return;
2787 }
2788
2789 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
2790 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2791 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
2792 GFP_KERNEL);
2793
2794 if (!skb) {
2795 hddLog(VOS_TRACE_LEVEL_ERROR,
2796 FL("cfg80211_vendor_event_alloc failed"));
2797 return;
2798 }
2799 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering "));
2800 hddLog(VOS_TRACE_LEVEL_INFO, "Scan event type (%u)",
2801 pData->extScanEventType);
2802 hddLog(VOS_TRACE_LEVEL_INFO, "Scan event status (%u)",
2803 pData->status);
2804
2805 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
2806 pData->extScanEventType) ||
2807 nla_put_u32(skb,
Dasari Srinivas5a288652014-06-30 17:13:22 +05302808 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
2809 pData->requestId) ||
2810 nla_put_u32(skb,
Dino Mycle6fb96c12014-06-10 11:52:40 +05302811 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_STATUS,
2812 pData->status)) {
2813 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
2814 goto nla_put_failure;
2815 }
2816
2817 cfg80211_vendor_event(skb, GFP_KERNEL);
2818 return;
2819
2820nla_put_failure:
2821 kfree_skb(skb);
2822 return;
2823}
2824
2825void wlan_hdd_cfg80211_extscan_callback(void *ctx, const tANI_U16 evType,
2826 void *pMsg)
2827{
2828 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
2829
2830 if (wlan_hdd_validate_context(pHddCtx)) {
2831 hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid"));
2832 return;
2833 }
2834
2835 hddLog(VOS_TRACE_LEVEL_INFO, FL("Rcvd Event (%d)"), evType);
2836
2837
2838 switch(evType) {
2839 case SIR_HAL_EXTSCAN_START_RSP:
2840 wlan_hdd_cfg80211_extscan_start_rsp(ctx, pMsg);
2841 break;
2842
2843 case SIR_HAL_EXTSCAN_STOP_RSP:
2844 wlan_hdd_cfg80211_extscan_stop_rsp(ctx, pMsg);
2845 break;
2846 case SIR_HAL_EXTSCAN_GET_CACHED_RESULTS_RSP:
2847 /* There is no need to send this response to upper layer
2848 Just log the message */
2849 hddLog(VOS_TRACE_LEVEL_INFO,
2850 FL("Rcvd SIR_HAL_EXTSCAN_CACHED_RESULTS_RSP"));
2851 break;
2852 case SIR_HAL_EXTSCAN_SET_BSS_HOTLIST_RSP:
2853 wlan_hdd_cfg80211_extscan_set_bss_hotlist_rsp(ctx, pMsg);
2854 break;
2855
2856 case SIR_HAL_EXTSCAN_RESET_BSS_HOTLIST_RSP:
2857 wlan_hdd_cfg80211_extscan_reset_bss_hotlist_rsp(ctx, pMsg);
2858 break;
2859
2860 case SIR_HAL_EXTSCAN_SET_SIGNF_RSSI_CHANGE_RSP:
2861 wlan_hdd_cfg80211_extscan_set_signf_wifi_change_rsp(ctx, pMsg);
2862 break;
2863
2864 case SIR_HAL_EXTSCAN_RESET_SIGNF_RSSI_CHANGE_RSP:
2865 wlan_hdd_cfg80211_extscan_reset_signf_wifi_change_rsp(ctx, pMsg);
2866 break;
2867 case SIR_HAL_EXTSCAN_GET_CAPABILITIES_RSP:
2868 wlan_hdd_cfg80211_extscan_get_capabilities_ind(ctx, pMsg);
2869 break;
2870 case SIR_HAL_EXTSCAN_PROGRESS_IND:
2871 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx, pMsg);
2872 break;
2873 case SIR_HAL_EXTSCAN_SCAN_AVAILABLE_IND:
2874 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx, pMsg);
2875 break;
2876 case SIR_HAL_EXTSCAN_SCAN_RESULT_IND:
2877 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
2878 break;
2879 case SIR_HAL_EXTSCAN_HOTLIST_MATCH_IND:
2880 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
2881 break;
2882 case SIR_HAL_EXTSCAN_SIGNF_WIFI_CHANGE_IND:
2883 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx, pMsg);
2884 break;
2885 case SIR_HAL_EXTSCAN_FULL_SCAN_RESULT_IND:
2886 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx, pMsg);
2887 break;
2888 default:
2889 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid event type %d "), evType);
2890 break;
2891 }
2892}
2893
2894static int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
2895 struct wireless_dev *wdev,
2896 void *data, int dataLen)
2897{
Dino Myclee8843b32014-07-04 14:21:45 +05302898 tSirGetEXTScanCapabilitiesReqParams reqMsg;
Dino Mycle6fb96c12014-06-10 11:52:40 +05302899 struct net_device *dev = wdev->netdev;
2900 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2901 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2902 struct nlattr
2903 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2904 eHalStatus status;
2905
2906 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering"));
2907 status = wlan_hdd_validate_context(pHddCtx);
2908 if (0 != status)
2909 {
2910 hddLog(VOS_TRACE_LEVEL_ERROR,
2911 FL("HDD context is not valid"));
2912 return -EINVAL;
2913 }
Dino Myclee8843b32014-07-04 14:21:45 +05302914 /* check the EXTScan Capability */
2915 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
2916 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
2917 {
2918 hddLog(VOS_TRACE_LEVEL_ERROR,
2919 FL("EXTScan not enabled/supported by Firmware"));
2920 return -EINVAL;
2921 }
2922
Dino Mycle6fb96c12014-06-10 11:52:40 +05302923 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2924 data, dataLen,
2925 wlan_hdd_extscan_config_policy)) {
2926 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
2927 return -EINVAL;
2928 }
2929
2930 /* Parse and fetch request Id */
2931 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
2932 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
2933 return -EINVAL;
2934 }
2935
Dino Mycle6fb96c12014-06-10 11:52:40 +05302936
Dino Myclee8843b32014-07-04 14:21:45 +05302937 reqMsg.requestId = nla_get_u32(
Dino Mycle6fb96c12014-06-10 11:52:40 +05302938 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Dino Myclee8843b32014-07-04 14:21:45 +05302939 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05302940
Dino Myclee8843b32014-07-04 14:21:45 +05302941 reqMsg.sessionId = pAdapter->sessionId;
2942 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05302943
Dino Myclee8843b32014-07-04 14:21:45 +05302944 status = sme_EXTScanGetCapabilities(pHddCtx->hHal, &reqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05302945 if (!HAL_STATUS_SUCCESS(status)) {
2946 hddLog(VOS_TRACE_LEVEL_ERROR,
2947 FL("sme_EXTScanGetCapabilities failed(err=%d)"), status);
Dino Mycle6fb96c12014-06-10 11:52:40 +05302948 return -EINVAL;
2949 }
2950
2951 return 0;
2952}
2953
2954
2955static int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
2956 struct wireless_dev *wdev,
2957 void *data, int dataLen)
2958{
Dino Myclee8843b32014-07-04 14:21:45 +05302959 tSirEXTScanGetCachedResultsReqParams reqMsg;
Dino Mycle6fb96c12014-06-10 11:52:40 +05302960 struct net_device *dev = wdev->netdev;
2961 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2962 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2963 struct nlattr
2964 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2965 eHalStatus status;
2966
2967 status = wlan_hdd_validate_context(pHddCtx);
2968 if (0 != status)
2969 {
2970 hddLog(VOS_TRACE_LEVEL_ERROR,
2971 FL("HDD context is not valid"));
2972 return -EINVAL;
2973 }
Dino Myclee8843b32014-07-04 14:21:45 +05302974 /* check the EXTScan Capability */
2975 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
2976 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
2977 {
2978 hddLog(VOS_TRACE_LEVEL_ERROR,
2979 FL("EXTScan not enabled/supported by Firmware"));
2980 return -EINVAL;
2981 }
2982
Dino Mycle6fb96c12014-06-10 11:52:40 +05302983 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2984 data, dataLen,
2985 wlan_hdd_extscan_config_policy)) {
2986 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
2987 return -EINVAL;
2988 }
2989 /* Parse and fetch request Id */
2990 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
2991 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
2992 return -EINVAL;
2993 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05302994
Dino Myclee8843b32014-07-04 14:21:45 +05302995 reqMsg.requestId = nla_get_u32(
Dino Mycle6fb96c12014-06-10 11:52:40 +05302996 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
2997
Dino Myclee8843b32014-07-04 14:21:45 +05302998 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05302999
Dino Myclee8843b32014-07-04 14:21:45 +05303000 reqMsg.sessionId = pAdapter->sessionId;
3001 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303002
3003 /* Parse and fetch flush parameter */
3004 if (!tb
3005 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH])
3006 {
3007 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr flush failed"));
3008 goto failed;
3009 }
Dino Myclee8843b32014-07-04 14:21:45 +05303010 reqMsg.flush = nla_get_u8(
Dino Mycle6fb96c12014-06-10 11:52:40 +05303011 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH]);
3012
Dino Myclee8843b32014-07-04 14:21:45 +05303013 hddLog(VOS_TRACE_LEVEL_INFO, FL("Flush (%d)"), reqMsg.flush);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303014
Dino Myclee8843b32014-07-04 14:21:45 +05303015 status = sme_getCachedResults(pHddCtx->hHal, &reqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303016 if (!HAL_STATUS_SUCCESS(status)) {
3017 hddLog(VOS_TRACE_LEVEL_ERROR,
3018 FL("sme_getCachedResults failed(err=%d)"), status);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303019 return -EINVAL;
3020 }
3021 return 0;
3022
3023failed:
Dino Mycle6fb96c12014-06-10 11:52:40 +05303024 return -EINVAL;
3025}
3026
3027static int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
3028 struct wireless_dev *wdev,
3029 void *data, int dataLen)
3030{
3031 tpSirEXTScanSetBssidHotListReqParams pReqMsg = NULL;
3032 struct net_device *dev = wdev->netdev;
3033 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3034 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3035 struct nlattr
3036 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3037 struct nlattr
3038 *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3039 struct nlattr *apTh;
3040 eHalStatus status;
3041 tANI_U8 i = 0;
3042 int rem;
3043
3044 status = wlan_hdd_validate_context(pHddCtx);
3045 if (0 != status)
3046 {
3047 hddLog(VOS_TRACE_LEVEL_ERROR,
3048 FL("HDD context is not valid"));
3049 return -EINVAL;
3050 }
Dino Myclee8843b32014-07-04 14:21:45 +05303051 /* check the EXTScan Capability */
3052 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3053 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3054 {
3055 hddLog(VOS_TRACE_LEVEL_ERROR,
3056 FL("EXTScan not enabled/supported by Firmware"));
3057 return -EINVAL;
3058 }
3059
Dino Mycle6fb96c12014-06-10 11:52:40 +05303060 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3061 data, dataLen,
3062 wlan_hdd_extscan_config_policy)) {
3063 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3064 return -EINVAL;
3065 }
3066
3067 /* Parse and fetch request Id */
3068 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3069 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3070 return -EINVAL;
3071 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05303072 pReqMsg = (tpSirEXTScanSetBssidHotListReqParams)
3073 vos_mem_malloc(sizeof(*pReqMsg));
3074 if (!pReqMsg) {
3075 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
3076 return -ENOMEM;
3077 }
3078
Dino Myclee8843b32014-07-04 14:21:45 +05303079
Dino Mycle6fb96c12014-06-10 11:52:40 +05303080 pReqMsg->requestId = nla_get_u32(
3081 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3082 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), pReqMsg->requestId);
3083
3084 /* Parse and fetch number of APs */
3085 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
3086 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr number of AP failed"));
3087 goto fail;
3088 }
3089
3090 pReqMsg->sessionId = pAdapter->sessionId;
3091 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), pReqMsg->sessionId);
3092
3093 pReqMsg->numAp = nla_get_u32(
3094 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
3095 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of AP (%d)"), pReqMsg->numAp);
3096
3097 nla_for_each_nested(apTh,
3098 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) {
3099 if(nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3100 nla_data(apTh), nla_len(apTh),
3101 NULL)) {
3102 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3103 goto fail;
3104 }
3105
3106 /* Parse and fetch MAC address */
3107 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
3108 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac address failed"));
3109 goto fail;
3110 }
3111 memcpy(pReqMsg->ap[i].bssid, nla_data(
3112 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]),
3113 sizeof(tSirMacAddr));
3114 hddLog(VOS_TRACE_LEVEL_INFO, FL("BSSID: %pM "), pReqMsg->ap[i].bssid);
3115
3116 /* Parse and fetch low RSSI */
3117 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
3118 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr low RSSI failed"));
3119 goto fail;
3120 }
3121 pReqMsg->ap[i].low = nla_get_s32(
3122 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
3123 hddLog(VOS_TRACE_LEVEL_INFO, FL("RSSI low (%d)"), pReqMsg->ap[i].low);
3124
3125 /* Parse and fetch high RSSI */
3126 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
3127 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr high RSSI failed"));
3128 goto fail;
3129 }
3130 pReqMsg->ap[i].high = nla_get_s32(
3131 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
3132 hddLog(VOS_TRACE_LEVEL_INFO, FL("RSSI High (%d)"),
3133 pReqMsg->ap[i].high);
3134
3135 /* Parse and fetch channel */
3136 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]) {
3137 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
3138 goto fail;
3139 }
3140 pReqMsg->ap[i].channel = nla_get_u32(
3141 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]);
3142 hddLog(VOS_TRACE_LEVEL_INFO,
3143 FL("Channel (%u)"), pReqMsg->ap[i].channel);
3144 i++;
3145 }
3146 status = sme_SetBssHotlist(pHddCtx->hHal, pReqMsg);
3147 if (!HAL_STATUS_SUCCESS(status)) {
3148 hddLog(VOS_TRACE_LEVEL_ERROR,
3149 FL("sme_SetBssHotlist failed(err=%d)"), status);
3150 vos_mem_free(pReqMsg);
3151 return -EINVAL;
3152 }
3153
Dino Myclee8843b32014-07-04 14:21:45 +05303154 vos_mem_free(pReqMsg);
3155
Dino Mycle6fb96c12014-06-10 11:52:40 +05303156 return 0;
3157
3158fail:
3159 vos_mem_free(pReqMsg);
3160 return -EINVAL;
3161}
3162
3163static int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
3164 struct wireless_dev *wdev,
3165 void *data, int dataLen)
3166{
3167 tpSirEXTScanSetSignificantChangeReqParams pReqMsg = NULL;
3168 struct net_device *dev = wdev->netdev;
3169 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3170 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3171 struct nlattr
3172 *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3173 struct nlattr
3174 *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3175 struct nlattr *apTh;
3176 eHalStatus status;
3177 int i = 0;
3178 int rem;
3179
3180 status = wlan_hdd_validate_context(pHddCtx);
3181 if (0 != status)
3182 {
3183 hddLog(VOS_TRACE_LEVEL_ERROR,
3184 FL("HDD context is not valid"));
3185 return -EINVAL;
3186 }
Dino Myclee8843b32014-07-04 14:21:45 +05303187 /* check the EXTScan Capability */
3188 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3189 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3190 {
3191 hddLog(VOS_TRACE_LEVEL_ERROR,
3192 FL("EXTScan not enabled/supported by Firmware"));
3193 return -EINVAL;
3194 }
3195
Dino Mycle6fb96c12014-06-10 11:52:40 +05303196 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3197 data, dataLen,
3198 wlan_hdd_extscan_config_policy)) {
3199 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3200 return -EINVAL;
3201 }
3202
3203 /* Parse and fetch request Id */
3204 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3205 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3206 return -EINVAL;
3207 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05303208 pReqMsg = (tpSirEXTScanSetSignificantChangeReqParams)
Dino Myclee8843b32014-07-04 14:21:45 +05303209 vos_mem_malloc(sizeof(*pReqMsg));
Dino Mycle6fb96c12014-06-10 11:52:40 +05303210 if (!pReqMsg) {
Dino Myclee8843b32014-07-04 14:21:45 +05303211 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
3212 return -ENOMEM;
Dino Mycle6fb96c12014-06-10 11:52:40 +05303213 }
3214
Dino Myclee8843b32014-07-04 14:21:45 +05303215
3216
Dino Mycle6fb96c12014-06-10 11:52:40 +05303217 pReqMsg->requestId = nla_get_u32(
3218 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3219 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), pReqMsg->requestId);
3220
3221 /* Parse and fetch RSSI sample size */
3222 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE])
3223 {
3224 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr RSSI sample size failed"));
3225 goto fail;
3226 }
3227 pReqMsg->rssiSampleSize = nla_get_u32(
3228 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
3229 hddLog(VOS_TRACE_LEVEL_INFO,
3230 FL("RSSI sample size (%u)"), pReqMsg->rssiSampleSize);
3231
3232 /* Parse and fetch lost AP sample size */
3233 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE])
3234 {
3235 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr lost AP sample size failed"));
3236 goto fail;
3237 }
3238 pReqMsg->lostApSampleSize = nla_get_u32(
3239 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
3240 hddLog(VOS_TRACE_LEVEL_INFO,
3241 FL("Lost AP sample size (%u)"), pReqMsg->lostApSampleSize);
3242 /* Parse and fetch minimum Breaching */
3243 if (!tb
3244 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
3245 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr minBreaching failed"));
3246 goto fail;
3247 }
3248 pReqMsg->minBreaching = nla_get_u32(
3249 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
3250 hddLog(VOS_TRACE_LEVEL_INFO, FL(" Breaching (%d)"), pReqMsg->minBreaching);
3251
3252 /* Parse and fetch number of APs */
3253 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
3254 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr number of AP failed"));
3255 goto fail;
3256 }
3257 pReqMsg->numAp = nla_get_u32(
3258 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
3259 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of AP (%d)"), pReqMsg->numAp);
3260
3261 pReqMsg->sessionId = pAdapter->sessionId;
3262 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), pReqMsg->sessionId);
3263
3264 nla_for_each_nested(apTh,
3265 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) {
3266 if(nla_parse(tb2,
3267 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3268 nla_data(apTh), nla_len(apTh),
3269 NULL)) {
3270 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3271 goto fail;
3272 }
3273
3274 /* Parse and fetch MAC address */
3275 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
3276 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr mac address failed"));
3277 goto fail;
3278 }
3279 memcpy(pReqMsg->ap[i].bssid, nla_data(
3280 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]),
3281 sizeof(tSirMacAddr));
3282
3283 /* Parse and fetch low RSSI */
3284 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
3285 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr low RSSI failed"));
3286 goto fail;
3287 }
3288 pReqMsg->ap[i].low = nla_get_s32(
3289 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
3290 hddLog(VOS_TRACE_LEVEL_INFO, FL("RSSI low (%d)"), pReqMsg->ap[i].low);
3291
3292 /* Parse and fetch high RSSI */
3293 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
3294 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr high RSSI failed"));
3295 goto fail;
3296 }
3297 pReqMsg->ap[i].high = nla_get_s32(
3298 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
3299 hddLog(VOS_TRACE_LEVEL_INFO,
3300 FL("RSSI High (%d)"), pReqMsg->ap[i].high);
3301
3302 /* Parse and fetch channel */
3303 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]) {
3304 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
3305 goto fail;
3306 }
3307 pReqMsg->ap[i].channel = nla_get_u32(
3308 tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL]);
3309 hddLog(VOS_TRACE_LEVEL_INFO,
3310 FL("Channel (%u)"), pReqMsg->ap[i].channel);
3311 i++;
3312 }
3313
3314 status = sme_SetSignificantChange(pHddCtx->hHal, pReqMsg);
3315 if (!HAL_STATUS_SUCCESS(status)) {
3316 hddLog(VOS_TRACE_LEVEL_ERROR,
3317 FL("sme_SetSignificantChange failed(err=%d)"), status);
3318 vos_mem_free(pReqMsg);
3319 return -EINVAL;
3320 }
Dino Myclee8843b32014-07-04 14:21:45 +05303321 vos_mem_free(pReqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303322 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Exiting"));
3323 return 0;
3324
3325fail:
3326 vos_mem_free(pReqMsg);
3327 return -EINVAL;
3328}
3329
3330static int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
3331 struct wireless_dev *wdev,
3332 void *data, int dataLen)
3333{
3334 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3335 tANI_U32 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3336 tANI_U8 numChannels = 0;
3337 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3338 tANI_U32 requestId;
3339 tWifiBand wifiBand;
3340 eHalStatus status;
3341 struct sk_buff *replySkb;
3342 tANI_U8 i;
3343
3344 hddLog(VOS_TRACE_LEVEL_INFO, FL("Entering"));
3345 status = wlan_hdd_validate_context(pHddCtx);
3346 if (0 != status)
3347 {
3348 hddLog(VOS_TRACE_LEVEL_ERROR,
3349 FL("HDD context is not valid"));
3350 return -EINVAL;
3351 }
Dino Myclee8843b32014-07-04 14:21:45 +05303352 /* check the EXTScan Capability */
3353 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3354 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3355 {
3356 hddLog(VOS_TRACE_LEVEL_ERROR,
3357 FL("EXTScan not enabled/supported by Firmware"));
3358 return -EINVAL;
3359 }
3360
Dino Mycle6fb96c12014-06-10 11:52:40 +05303361 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3362 data, dataLen,
3363 wlan_hdd_extscan_config_policy)) {
3364 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3365 return -EINVAL;
3366 }
3367
3368 /* Parse and fetch request Id */
3369 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3370 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3371 return -EINVAL;
3372 }
3373 requestId = nla_get_u32(
3374 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3375 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), requestId);
3376
3377 /* Parse and fetch wifi band */
3378 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND])
3379 {
3380 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr wifi band failed"));
3381 return -EINVAL;
3382 }
3383 wifiBand = nla_get_u32(
3384 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
3385 hddLog(VOS_TRACE_LEVEL_INFO, FL("Wifi band (%d)"), wifiBand);
3386
3387 status = sme_GetValidChannelsByBand((tHalHandle)(pHddCtx->hHal),
3388 wifiBand, ChannelList,
3389 &numChannels);
3390 if (eHAL_STATUS_SUCCESS != status) {
3391 hddLog(VOS_TRACE_LEVEL_ERROR,
3392 FL("sme_GetValidChannelsByBand failed (err=%d)"), status);
3393 return -EINVAL;
3394 }
3395 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of channels (%d)"), numChannels);
3396 for (i = 0; i < numChannels; i++)
3397 hddLog(VOS_TRACE_LEVEL_INFO, "Channel: %u ", ChannelList[i]);
3398
3399 replySkb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
3400 sizeof(u32) * numChannels +
3401 NLMSG_HDRLEN);
3402
3403 if (!replySkb) {
3404 hddLog(VOS_TRACE_LEVEL_ERROR,
3405 FL("valid channels: buffer alloc fail"));
3406 return -EINVAL;
3407 }
3408 if (nla_put_u32(replySkb,
3409 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
3410 numChannels) ||
3411 nla_put(replySkb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
3412 sizeof(u32) * numChannels, ChannelList)) {
3413
3414 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla put fail"));
3415 kfree_skb(replySkb);
3416 return -EINVAL;
3417 }
3418
3419 return cfg80211_vendor_cmd_reply(replySkb);
3420}
3421
3422static int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3423 struct wireless_dev *wdev,
3424 void *data, int dataLen)
3425{
Dino Myclee8843b32014-07-04 14:21:45 +05303426 tpSirEXTScanStartReqParams pReqMsg = NULL;
Dino Mycle6fb96c12014-06-10 11:52:40 +05303427 struct net_device *dev = wdev->netdev;
3428 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3429 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3430 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3431 struct nlattr *bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3432 struct nlattr *channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3433 struct nlattr *buckets;
3434 struct nlattr *channels;
3435 int rem1;
3436 int rem2;
3437 eHalStatus status;
3438 tANI_U8 bktIndex;
3439 tANI_U32 i = 0, j = 0;
3440
3441 status = wlan_hdd_validate_context(pHddCtx);
3442 if (0 != status)
3443 {
3444 hddLog(VOS_TRACE_LEVEL_ERROR,
3445 FL("HDD context is not valid"));
3446 return -EINVAL;
3447 }
Dino Myclee8843b32014-07-04 14:21:45 +05303448 /* check the EXTScan Capability */
3449 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3450 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3451 {
3452 hddLog(VOS_TRACE_LEVEL_ERROR,
3453 FL("EXTScan not enabled/supported by Firmware"));
3454 return -EINVAL;
3455 }
3456
Dino Mycle6fb96c12014-06-10 11:52:40 +05303457 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3458 data, dataLen,
3459 wlan_hdd_extscan_config_policy)) {
3460 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3461 return -EINVAL;
3462 }
3463
3464 /* Parse and fetch request Id */
3465 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3466 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3467 return -EINVAL;
3468 }
3469
Dino Myclee8843b32014-07-04 14:21:45 +05303470 pReqMsg = (tpSirEXTScanStartReqParams)
3471 vos_mem_malloc(sizeof(*pReqMsg));
Dino Mycle6fb96c12014-06-10 11:52:40 +05303472 if (!pReqMsg) {
Dino Myclee8843b32014-07-04 14:21:45 +05303473 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos_mem_malloc failed"));
3474 return -ENOMEM;
Dino Mycle6fb96c12014-06-10 11:52:40 +05303475 }
3476
3477 pReqMsg->requestId = nla_get_u32(
3478 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3479 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), pReqMsg->requestId);
3480
3481 pReqMsg->sessionId = pAdapter->sessionId;
3482 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), pReqMsg->sessionId);
3483
3484 /* Parse and fetch base period */
3485 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD]) {
3486 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr base period failed"));
3487 goto fail;
3488 }
3489 pReqMsg->basePeriod = nla_get_u32(
3490 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD]);
3491 hddLog(VOS_TRACE_LEVEL_INFO, FL("Base Period (%d)"),
3492 pReqMsg->basePeriod);
3493
3494 /* Parse and fetch max AP per scan */
3495 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN]) {
3496 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr max_ap_per_scan failed"));
3497 goto fail;
3498 }
3499 pReqMsg->maxAPperScan = nla_get_u32(
3500 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN]);
3501 hddLog(VOS_TRACE_LEVEL_INFO, FL("Max AP per Scan (%d)"),
3502 pReqMsg->maxAPperScan);
3503
3504 /* Parse and fetch report threshold */
3505 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD]) {
3506 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr report_threshold failed"));
3507 goto fail;
3508 }
3509 pReqMsg->reportThreshold = nla_get_u8(
3510 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD]);
3511 hddLog(VOS_TRACE_LEVEL_INFO, FL("Report Threshold (%d)"),
3512 pReqMsg->reportThreshold);
3513
3514 /* Parse and fetch number of buckets */
3515 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS]) {
3516 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr number of buckets failed"));
3517 goto fail;
3518 }
3519 pReqMsg->numBuckets = nla_get_u8(
3520 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS]);
3521 if (pReqMsg->numBuckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3522 hddLog(VOS_TRACE_LEVEL_WARN, FL("Exceeded MAX number of buckets "
3523 "Setting numBuckets to %u"), WLAN_EXTSCAN_MAX_BUCKETS);
3524 pReqMsg->numBuckets = WLAN_EXTSCAN_MAX_BUCKETS;
3525 }
3526 hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of Buckets (%d)"),
3527 pReqMsg->numBuckets);
3528 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
3529 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bucket spec failed"));
3530 goto fail;
3531 }
3532
3533 nla_for_each_nested(buckets,
3534 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
3535 if(nla_parse(bucket,
3536 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3537 nla_data(buckets), nla_len(buckets), NULL)) { //policy
3538 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3539 goto fail;
3540 }
3541
3542 /* Parse and fetch bucket spec */
3543 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
3544 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr bucket index failed"));
3545 goto fail;
3546 }
3547 bktIndex = nla_get_u8(
3548 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
3549 hddLog(VOS_TRACE_LEVEL_INFO, FL("Bucket spec Index (%d)"), bktIndex);
3550 pReqMsg->buckets[bktIndex].bucket = bktIndex;
3551
3552 /* Parse and fetch wifi band */
3553 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
3554 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr wifi band failed"));
3555 goto fail;
3556 }
3557 pReqMsg->buckets[bktIndex].band = nla_get_u8(
3558 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
3559 hddLog(VOS_TRACE_LEVEL_INFO, FL("Wifi band (%d)"),
3560 pReqMsg->buckets[bktIndex].band);
3561
3562 /* Parse and fetch period */
3563 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
3564 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr period failed"));
3565 goto fail;
3566 }
3567 pReqMsg->buckets[bktIndex].period = nla_get_u32(
3568 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
3569 hddLog(VOS_TRACE_LEVEL_INFO, FL("period (%d)"),
3570 pReqMsg->buckets[bktIndex].period);
3571
3572 /* Parse and fetch report events */
3573 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
3574 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr report events failed"));
3575 goto fail;
3576 }
3577 pReqMsg->buckets[bktIndex].reportEvents = nla_get_u8(
3578 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
3579 hddLog(VOS_TRACE_LEVEL_INFO, FL("report events (%d)"),
3580 pReqMsg->buckets[bktIndex].reportEvents);
3581
3582 /* Parse and fetch number of channels */
3583 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
3584 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr num channels failed"));
3585 goto fail;
3586 }
3587 pReqMsg->buckets[bktIndex].numChannels = nla_get_u32(
3588 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
3589 hddLog(VOS_TRACE_LEVEL_INFO, FL("num channels (%d)"),
3590 pReqMsg->buckets[bktIndex].numChannels);
3591
3592 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
3593 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel spec failed"));
3594 goto fail;
3595 }
3596
3597 j = 0;
3598 nla_for_each_nested(channels,
3599 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
3600 if(nla_parse(channel,
3601 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3602 nla_data(channels), nla_len(channels),
3603 NULL)) { //wlan_hdd_extscan_config_policy here
3604 hddLog(VOS_TRACE_LEVEL_ERROR, FL("nla_parse failed"));
3605 goto fail;
3606 }
3607
3608 /* Parse and fetch channel */
3609 if (!channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
3610 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr channel failed"));
3611 goto fail;
3612 }
3613 pReqMsg->buckets[bktIndex].channels[j].channel = nla_get_u32(
3614 channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
3615 hddLog(VOS_TRACE_LEVEL_INFO, FL("channel (%u)"),
3616 pReqMsg->buckets[bktIndex].channels[j].channel);
3617
3618 /* Parse and fetch dwell time */
3619 if (!channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
3620 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr dwelltime failed"));
3621 goto fail;
3622 }
3623 pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs = nla_get_u32(
3624 channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
3625 hddLog(VOS_TRACE_LEVEL_INFO, FL("Dwell time (%u ms)"),
3626 pReqMsg->buckets[bktIndex].channels[j].dwellTimeMs);
3627
3628 /* Parse and fetch channel spec passive */
3629 if (!channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
3630 hddLog(VOS_TRACE_LEVEL_ERROR,
3631 FL("attr channel spec passive failed"));
3632 goto fail;
3633 }
3634 pReqMsg->buckets[bktIndex].channels[j].passive = nla_get_u8(
3635 channel[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
3636 hddLog(VOS_TRACE_LEVEL_INFO, FL("Chnl spec passive (%u)"),
3637 pReqMsg->buckets[bktIndex].channels[j].passive);
3638 j++;
3639 }
3640 i++;
3641 }
3642 status = sme_EXTScanStart(pHddCtx->hHal, pReqMsg);
3643 if (!HAL_STATUS_SUCCESS(status)) {
3644 hddLog(VOS_TRACE_LEVEL_ERROR,
3645 FL("sme_EXTScanStart failed(err=%d)"), status);
3646 vos_mem_free(pReqMsg);
3647 return -EINVAL;
3648 }
3649
Dino Myclee8843b32014-07-04 14:21:45 +05303650 vos_mem_free(pReqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303651 return 0;
3652
3653fail:
3654 vos_mem_free(pReqMsg);
3655 return -EINVAL;
3656}
3657
3658static int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3659 struct wireless_dev *wdev,
3660 void *data, int dataLen)
3661{
Dino Myclee8843b32014-07-04 14:21:45 +05303662 tSirEXTScanStopReqParams reqMsg;
Dino Mycle6fb96c12014-06-10 11:52:40 +05303663 struct net_device *dev = wdev->netdev;
3664 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3665 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3666 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3667 eHalStatus status;
3668
3669 status = wlan_hdd_validate_context(pHddCtx);
3670 if (0 != status)
3671 {
3672 hddLog(VOS_TRACE_LEVEL_ERROR,
3673 FL("HDD context is not valid"));
3674 return -EINVAL;
3675 }
Dino Myclee8843b32014-07-04 14:21:45 +05303676 /* check the EXTScan Capability */
3677 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3678 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3679 {
3680 hddLog(VOS_TRACE_LEVEL_ERROR,
3681 FL("EXTScan not enabled/supported by Firmware"));
3682 return -EINVAL;
3683 }
3684
Dino Mycle6fb96c12014-06-10 11:52:40 +05303685 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3686 data, dataLen,
3687 wlan_hdd_extscan_config_policy)) {
3688 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3689 return -EINVAL;
3690 }
3691
3692 /* Parse and fetch request Id */
3693 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3694 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3695 return -EINVAL;
3696 }
3697
Dino Myclee8843b32014-07-04 14:21:45 +05303698 reqMsg.requestId = nla_get_u32(
Dino Mycle6fb96c12014-06-10 11:52:40 +05303699 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Dino Myclee8843b32014-07-04 14:21:45 +05303700 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303701
Dino Myclee8843b32014-07-04 14:21:45 +05303702 reqMsg.sessionId = pAdapter->sessionId;
3703 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303704
Dino Myclee8843b32014-07-04 14:21:45 +05303705 status = sme_EXTScanStop(pHddCtx->hHal, &reqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303706 if (!HAL_STATUS_SUCCESS(status)) {
3707 hddLog(VOS_TRACE_LEVEL_ERROR,
3708 FL("sme_EXTScanStop failed(err=%d)"), status);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303709 return -EINVAL;
3710 }
3711
3712 return 0;
3713}
3714
3715static int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3716 struct wireless_dev *wdev,
3717 void *data, int dataLen)
3718{
Dino Myclee8843b32014-07-04 14:21:45 +05303719 tSirEXTScanResetBssidHotlistReqParams reqMsg;
Dino Mycle6fb96c12014-06-10 11:52:40 +05303720 struct net_device *dev = wdev->netdev;
3721 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3722 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3723 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3724 eHalStatus status;
3725
3726 status = wlan_hdd_validate_context(pHddCtx);
3727 if (0 != status)
3728 {
3729 hddLog(VOS_TRACE_LEVEL_ERROR,
3730 FL("HDD context is not valid"));
3731 return -EINVAL;
3732 }
Dino Myclee8843b32014-07-04 14:21:45 +05303733 /* check the EXTScan Capability */
3734 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3735 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3736 {
3737 hddLog(VOS_TRACE_LEVEL_ERROR,
3738 FL("EXTScan not enabled/supported by Firmware"));
3739 return -EINVAL;
3740 }
3741
Dino Mycle6fb96c12014-06-10 11:52:40 +05303742 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3743 data, dataLen,
3744 wlan_hdd_extscan_config_policy)) {
3745 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3746 return -EINVAL;
3747 }
3748
3749 /* Parse and fetch request Id */
3750 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3751 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3752 return -EINVAL;
3753 }
3754
Dino Myclee8843b32014-07-04 14:21:45 +05303755 reqMsg.requestId = nla_get_u32(
Dino Mycle6fb96c12014-06-10 11:52:40 +05303756 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Dino Myclee8843b32014-07-04 14:21:45 +05303757 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303758
Dino Myclee8843b32014-07-04 14:21:45 +05303759 reqMsg.sessionId = pAdapter->sessionId;
3760 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303761
Dino Myclee8843b32014-07-04 14:21:45 +05303762 status = sme_ResetBssHotlist(pHddCtx->hHal, &reqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303763 if (!HAL_STATUS_SUCCESS(status)) {
3764 hddLog(VOS_TRACE_LEVEL_ERROR,
3765 FL("sme_ResetBssHotlist failed(err=%d)"), status);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303766 return -EINVAL;
3767 }
3768
3769 return 0;
3770}
3771
3772static int wlan_hdd_cfg80211_extscan_reset_significant_change(
3773 struct wiphy *wiphy,
3774 struct wireless_dev *wdev,
3775 void *data, int dataLen)
3776{
Dino Myclee8843b32014-07-04 14:21:45 +05303777 tSirEXTScanResetSignificantChangeReqParams reqMsg;
Dino Mycle6fb96c12014-06-10 11:52:40 +05303778 struct net_device *dev = wdev->netdev;
3779 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3780 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3781 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3782 eHalStatus status;
3783
3784 hddLog(VOS_TRACE_LEVEL_INFO, FL(" Entering"));
3785 status = wlan_hdd_validate_context(pHddCtx);
3786 if (0 != status)
3787 {
3788 hddLog(VOS_TRACE_LEVEL_ERROR,
3789 FL("HDD context is not valid"));
3790 return -EINVAL;
3791 }
Dino Myclee8843b32014-07-04 14:21:45 +05303792 /* check the EXTScan Capability */
3793 if ( (TRUE != pHddCtx->cfg_ini->fEnableEXTScan) ||
3794 (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)))
3795 {
3796 hddLog(VOS_TRACE_LEVEL_ERROR,
3797 FL("EXTScan not enabled/supported by Firmware"));
3798 return -EINVAL;
3799 }
3800
Dino Mycle6fb96c12014-06-10 11:52:40 +05303801 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3802 data, dataLen,
3803 wlan_hdd_extscan_config_policy)) {
3804 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
3805 return -EINVAL;
3806 }
3807
3808 /* Parse and fetch request Id */
3809 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
3810 hddLog(VOS_TRACE_LEVEL_ERROR, FL("attr request id failed"));
3811 return -EINVAL;
3812 }
3813
Dino Mycle6fb96c12014-06-10 11:52:40 +05303814
Dino Myclee8843b32014-07-04 14:21:45 +05303815 reqMsg.requestId = nla_get_u32(
Dino Mycle6fb96c12014-06-10 11:52:40 +05303816 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Dino Myclee8843b32014-07-04 14:21:45 +05303817 hddLog(VOS_TRACE_LEVEL_INFO, FL("Req Id (%d)"), reqMsg.requestId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303818
Dino Myclee8843b32014-07-04 14:21:45 +05303819 reqMsg.sessionId = pAdapter->sessionId;
3820 hddLog(VOS_TRACE_LEVEL_INFO, FL("Session Id (%d)"), reqMsg.sessionId);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303821
Dino Myclee8843b32014-07-04 14:21:45 +05303822 status = sme_ResetSignificantChange(pHddCtx->hHal, &reqMsg);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303823 if (!HAL_STATUS_SUCCESS(status)) {
3824 hddLog(VOS_TRACE_LEVEL_ERROR,
3825 FL("sme_ResetSignificantChange failed(err=%d)"), status);
Dino Mycle6fb96c12014-06-10 11:52:40 +05303826 return -EINVAL;
3827 }
3828
3829 hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Exiting"));
3830 return 0;
3831}
3832
3833#endif /* WLAN_FEATURE_EXTSCAN */
3834
Sunil Duttc69bccb2014-05-26 21:30:20 +05303835const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] =
3836{
3837#ifdef WLAN_FEATURE_LINK_LAYER_STATS
3838 {
3839 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3840 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
3841 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3842 WIPHY_VENDOR_CMD_NEED_NETDEV |
3843 WIPHY_VENDOR_CMD_NEED_RUNNING,
3844 .doit = wlan_hdd_cfg80211_ll_stats_clear
3845 },
3846
3847 {
3848 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3849 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
3850 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3851 WIPHY_VENDOR_CMD_NEED_NETDEV |
3852 WIPHY_VENDOR_CMD_NEED_RUNNING,
3853 .doit = wlan_hdd_cfg80211_ll_stats_set
3854 },
3855
3856 {
3857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
3859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3860 WIPHY_VENDOR_CMD_NEED_NETDEV |
3861 WIPHY_VENDOR_CMD_NEED_RUNNING,
3862 .doit = wlan_hdd_cfg80211_ll_stats_get
Dino Mycle6fb96c12014-06-10 11:52:40 +05303863 },
Sunil Duttc69bccb2014-05-26 21:30:20 +05303864#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
Dino Mycle6fb96c12014-06-10 11:52:40 +05303865#ifdef WLAN_FEATURE_EXTSCAN
3866 {
3867 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3868 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
3869 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3870 WIPHY_VENDOR_CMD_NEED_NETDEV |
3871 WIPHY_VENDOR_CMD_NEED_RUNNING,
3872 .doit = wlan_hdd_cfg80211_extscan_start
3873 },
3874 {
3875 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3876 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
3877 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3878 WIPHY_VENDOR_CMD_NEED_NETDEV |
3879 WIPHY_VENDOR_CMD_NEED_RUNNING,
3880 .doit = wlan_hdd_cfg80211_extscan_stop
3881 },
3882 {
3883 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3884 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
3885 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3886 WIPHY_VENDOR_CMD_NEED_NETDEV,
3887 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
3888 },
3889 {
3890 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3891 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
3892 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3893 WIPHY_VENDOR_CMD_NEED_NETDEV |
3894 WIPHY_VENDOR_CMD_NEED_RUNNING,
3895 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
3896 },
3897 {
3898 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3899 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
3900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3901 WIPHY_VENDOR_CMD_NEED_NETDEV |
3902 WIPHY_VENDOR_CMD_NEED_RUNNING,
3903 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
3904 },
3905 {
3906 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3907 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
3908 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3909 WIPHY_VENDOR_CMD_NEED_NETDEV |
3910 WIPHY_VENDOR_CMD_NEED_RUNNING,
3911 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
3912 },
3913 {
3914 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3915 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
3916 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3917 WIPHY_VENDOR_CMD_NEED_NETDEV |
3918 WIPHY_VENDOR_CMD_NEED_RUNNING,
3919 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
3920 },
3921 {
3922 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3923 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
3924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3925 WIPHY_VENDOR_CMD_NEED_NETDEV |
3926 WIPHY_VENDOR_CMD_NEED_RUNNING,
3927 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
3928 },
3929 {
3930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
3931 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
3932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
3933 WIPHY_VENDOR_CMD_NEED_NETDEV |
3934 WIPHY_VENDOR_CMD_NEED_RUNNING,
3935 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
3936 },
3937#endif /* WLAN_FEATURE_EXTSCAN */
Sunil Duttc69bccb2014-05-26 21:30:20 +05303938};
3939
Rajesh Chauhan98a31f82014-01-06 20:15:25 -08003940/* vendor specific events */
Sunil Duttc69bccb2014-05-26 21:30:20 +05303941static const
3942struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
Rajesh Chauhan98a31f82014-01-06 20:15:25 -08003943{
3944#ifdef FEATURE_WLAN_CH_AVOID
3945 {
Sunil Duttc69bccb2014-05-26 21:30:20 +05303946 .vendor_id = QCA_NL80211_VENDOR_ID,
3947 .subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
Rajesh Chauhan98a31f82014-01-06 20:15:25 -08003948 },
Sunil Duttc69bccb2014-05-26 21:30:20 +05303949#endif /* FEATURE_WLAN_CH_AVOID Index = 0*/
3950#ifdef WLAN_FEATURE_LINK_LAYER_STATS
3951 {
3952 /* Index = 1*/
3953 .vendor_id = QCA_NL80211_VENDOR_ID,
3954 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
3955 },
3956 {
3957 /* Index = 2*/
3958 .vendor_id = QCA_NL80211_VENDOR_ID,
3959 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
3960 },
3961 {
3962 /* Index = 3*/
3963 .vendor_id = QCA_NL80211_VENDOR_ID,
3964 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
3965 },
3966 {
3967 /* Index = 4*/
3968 .vendor_id = QCA_NL80211_VENDOR_ID,
3969 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
3970 },
3971 {
3972 /* Index = 5*/
3973 .vendor_id = QCA_NL80211_VENDOR_ID,
3974 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
3975 },
3976 {
3977 /* Index = 6*/
3978 .vendor_id = QCA_NL80211_VENDOR_ID,
3979 .subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
3980 },
3981#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
Dino Mycle6fb96c12014-06-10 11:52:40 +05303982#ifdef WLAN_FEATURE_EXTSCAN
3983 {
3984 .vendor_id = QCA_NL80211_VENDOR_ID,
3985 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
3986 },
3987 {
3988 .vendor_id = QCA_NL80211_VENDOR_ID,
3989 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
3990 },
3991 {
3992 .vendor_id = QCA_NL80211_VENDOR_ID,
3993 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
3994 },
3995 {
3996 .vendor_id = QCA_NL80211_VENDOR_ID,
3997 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
3998 },
3999 {
4000 .vendor_id = QCA_NL80211_VENDOR_ID,
4001 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
4002 },
4003 {
4004 .vendor_id = QCA_NL80211_VENDOR_ID,
4005 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
4006 },
4007 {
4008 .vendor_id = QCA_NL80211_VENDOR_ID,
4009 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
4010 },
4011 {
4012 .vendor_id = QCA_NL80211_VENDOR_ID,
4013 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
4014 },
4015 {
4016 .vendor_id = QCA_NL80211_VENDOR_ID,
4017 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
4018 },
4019 {
4020 .vendor_id = QCA_NL80211_VENDOR_ID,
4021 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
4022 },
4023 {
4024 .vendor_id = QCA_NL80211_VENDOR_ID,
4025 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
4026 },
4027 {
4028 .vendor_id = QCA_NL80211_VENDOR_ID,
4029 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
4030 },
4031 {
4032 .vendor_id = QCA_NL80211_VENDOR_ID,
4033 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
4034 },
4035#endif /* WLAN_FEATURE_EXTSCAN */
Sunil Duttc69bccb2014-05-26 21:30:20 +05304036
Rajesh Chauhan98a31f82014-01-06 20:15:25 -08004037};
4038
Jeff Johnson295189b2012-06-20 16:38:30 -07004039/*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304040 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304041 * This function is called by hdd_wlan_startup()
4042 * during initialization.
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304043 * This function is used to allocate wiphy structure.
Jeff Johnson295189b2012-06-20 16:38:30 -07004044 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304045struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
Jeff Johnson295189b2012-06-20 16:38:30 -07004046{
4047 struct wiphy *wiphy;
4048 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304049 /*
4050 * Create wiphy device
Jeff Johnson295189b2012-06-20 16:38:30 -07004051 */
4052 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
4053
4054 if (!wiphy)
4055 {
4056 /* Print error and jump into err label and free the memory */
4057 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wiphy init failed", __func__);
4058 return NULL;
4059 }
4060
Sunil Duttc69bccb2014-05-26 21:30:20 +05304061
Jeff Johnson295189b2012-06-20 16:38:30 -07004062 return wiphy;
4063}
4064
4065/*
4066 * FUNCTION: wlan_hdd_cfg80211_update_band
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304067 * This function is called from the supplicant through a
Jeff Johnson295189b2012-06-20 16:38:30 -07004068 * private ioctl to change the band value
4069 */
4070int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
4071{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +05304072 int i, j;
4073 eNVChannelEnabledType channelEnabledState;
4074
Jeff Johnsone7245742012-09-05 17:12:55 -07004075 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304076
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +05304077 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
Jeff Johnson295189b2012-06-20 16:38:30 -07004078 {
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +05304079
4080 if (NULL == wiphy->bands[i])
4081 {
4082 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
4083 __func__, i);
4084 continue;
4085 }
4086
4087 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
4088 {
4089 struct ieee80211_supported_band *band = wiphy->bands[i];
4090
4091 channelEnabledState = vos_nv_getChannelEnabledState(
4092 band->channels[j].hw_value);
4093
4094 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only
4095 {
4096 // Enable Social channels for P2P
4097 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) &&
4098 NV_CHANNEL_ENABLE == channelEnabledState)
4099 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
4100 else
4101 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
4102 continue;
4103 }
4104 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only
4105 {
4106 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
4107 continue;
4108 }
4109
4110 if (NV_CHANNEL_DISABLE == channelEnabledState ||
4111 NV_CHANNEL_INVALID == channelEnabledState)
4112 {
4113 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
4114 }
4115 else if (NV_CHANNEL_DFS == channelEnabledState)
4116 {
4117 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
4118 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
4119 }
4120 else
4121 {
4122 band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED
4123 |IEEE80211_CHAN_RADAR);
4124 }
4125 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004126 }
4127 return 0;
4128}
4129/*
4130 * FUNCTION: wlan_hdd_cfg80211_init
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304131 * This function is called by hdd_wlan_startup()
4132 * during initialization.
Jeff Johnson295189b2012-06-20 16:38:30 -07004133 * This function is used to initialize and register wiphy structure.
4134 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304135int wlan_hdd_cfg80211_init(struct device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07004136 struct wiphy *wiphy,
4137 hdd_config_t *pCfg
4138 )
4139{
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +05304140 int i, j;
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05304141 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4142
Jeff Johnsone7245742012-09-05 17:12:55 -07004143 ENTER();
4144
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 /* Now bind the underlying wlan device with wiphy */
4146 set_wiphy_dev(wiphy, dev);
4147
4148 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
Amar Singhalfddc28c2013-09-05 13:03:40 -07004149
Kiet Lam6c583332013-10-14 05:37:09 +05304150#ifndef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07004151 /* the flag for the other case would be initialzed in
4152 vos_init_wiphy_from_nv_bin */
Amar Singhal0a402232013-10-11 20:57:16 -07004153 wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
Kiet Lam6c583332013-10-14 05:37:09 +05304154#endif
Amar Singhala49cbc52013-10-08 18:37:44 -07004155
Amar Singhalfddc28c2013-09-05 13:03:40 -07004156 /* This will disable updating of NL channels from passive to
4157 * active if a beacon is received on passive channel. */
4158 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhalf0073192013-09-20 12:34:56 -07004159
Amar Singhalfddc28c2013-09-05 13:03:40 -07004160
Amar Singhala49cbc52013-10-08 18:37:44 -07004161
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004162#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07004163 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
4164 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
4165 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
Jeff Johnsone7245742012-09-05 17:12:55 -07004166 | WIPHY_FLAG_OFFCHAN_TX;
Kiet Lam6c583332013-10-14 05:37:09 +05304167 wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004168#endif
Amar Singhala49cbc52013-10-08 18:37:44 -07004169
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004170#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowda640728a2013-03-28 12:21:54 -07004171 if (pCfg->isFastTransitionEnabled
James Zmuda77fb5ae2013-01-29 08:00:17 -08004172#ifdef FEATURE_WLAN_LFR
Srinivas Girigowda640728a2013-03-28 12:21:54 -07004173 || pCfg->isFastRoamIniFeatureEnabled
4174#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004175#ifdef FEATURE_WLAN_ESE
4176 || pCfg->isEseIniFeatureEnabled
Srinivas Girigowda640728a2013-03-28 12:21:54 -07004177#endif
4178 )
4179 {
4180 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
4181 }
James Zmuda77fb5ae2013-01-29 08:00:17 -08004182#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -08004183#ifdef FEATURE_WLAN_TDLS
4184 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
4185 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
4186#endif
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05304187#ifdef FEATURE_WLAN_SCAN_PNO
Hardik Kantilal Patel3dfd8792013-11-13 20:34:57 +05304188 if (pCfg->configPNOScanSupport)
4189 {
4190 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4191 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
4192 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
4193 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
4194 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +05304195#endif/*FEATURE_WLAN_SCAN_PNO*/
Mohit Khanna698ba2a2012-12-04 15:08:18 -08004196
Amar Singhalfddc28c2013-09-05 13:03:40 -07004197#ifdef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07004198 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
4199 driver can still register regulatory callback and
Amar Singhalfddc28c2013-09-05 13:03:40 -07004200 it will get regulatory settings in wiphy->band[], but
Madan Mohan Koyyalamudic3a240c2012-09-28 15:34:08 -07004201 driver need to determine what to do with both
4202 regulatory settings */
Amar Singhalfddc28c2013-09-05 13:03:40 -07004203
4204 wiphy->reg_notifier = wlan_hdd_linux_reg_notifier;
Amar Singhala49cbc52013-10-08 18:37:44 -07004205#else
4206 wiphy->reg_notifier = wlan_hdd_crda_reg_notifier;
Amar Singhalfddc28c2013-09-05 13:03:40 -07004207#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004208
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304209 wiphy->max_scan_ssids = MAX_SCAN_SSID;
4210
Madan Mohan Koyyalamudi6815b162013-07-19 17:17:46 +05304211 wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Jeff Johnson295189b2012-06-20 16:38:30 -07004212
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05304213 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
4214
Jeff Johnson295189b2012-06-20 16:38:30 -07004215 /* Supports STATION & AD-HOC modes right now */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304216 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07004217 | BIT(NL80211_IFTYPE_ADHOC)
Jeff Johnson295189b2012-06-20 16:38:30 -07004218 | BIT(NL80211_IFTYPE_P2P_CLIENT)
4219 | BIT(NL80211_IFTYPE_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07004220 | BIT(NL80211_IFTYPE_AP);
4221
Rashmi Ramannabd3feb72014-02-25 16:14:48 +05304222 if( pCfg->advertiseConcurrentOperation )
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -08004223 {
Rashmi Ramannabd3feb72014-02-25 16:14:48 +05304224#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
4225 if( pCfg->enableMCC )
4226 {
4227 /* Currently, supports up to two channels */
4228 wlan_hdd_iface_combination.num_different_channels = 2;
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -08004229
Rashmi Ramannabd3feb72014-02-25 16:14:48 +05304230 if( !pCfg->allowMCCGODiffBI )
4231 wlan_hdd_iface_combination.beacon_int_infra_match = true;
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -08004232
Rashmi Ramannabd3feb72014-02-25 16:14:48 +05304233 }
4234 wiphy->iface_combinations = &wlan_hdd_iface_combination;
4235 wiphy->n_iface_combinations = 1;
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -08004236#endif
Rashmi Ramannabd3feb72014-02-25 16:14:48 +05304237 }
Sudhir Sattayappa Kohalli278eee52013-01-16 17:35:13 -08004238
Jeff Johnson295189b2012-06-20 16:38:30 -07004239 /* Before registering we need to update the ht capabilitied based
4240 * on ini values*/
4241 if( !pCfg->ShortGI20MhzEnable )
4242 {
4243 wlan_hdd_band_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
4244 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
4245 wlan_hdd_band_p2p_2_4_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
4246 }
4247
4248 if( !pCfg->ShortGI40MhzEnable )
4249 {
4250 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
4251 }
4252
4253 if( !pCfg->nChannelBondingMode5GHz )
4254 {
4255 wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
4256 }
4257
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +05304258 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ;
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05304259 if (true == hdd_is_5g_supported(pHddCtx))
4260 {
4261 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ;
4262 }
Gopichand Nakkala1f7a64f2013-04-01 18:37:17 +05304263
4264 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
4265 {
4266
4267 if (NULL == wiphy->bands[i])
4268 {
4269 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d",
4270 __func__, i);
4271 continue;
4272 }
4273
4274 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
4275 {
4276 struct ieee80211_supported_band *band = wiphy->bands[i];
4277
4278 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only
4279 {
4280 // Enable social channels for P2P
4281 if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq))
4282 band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
4283 else
4284 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
4285 continue;
4286 }
4287 else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only
4288 {
4289 band->channels[j].flags |= IEEE80211_CHAN_DISABLED;
4290 continue;
4291 }
4292 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004293 }
4294 /*Initialise the supported cipher suite details*/
4295 wiphy->cipher_suites = hdd_cipher_suites;
4296 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
4297
4298 /*signal strength in mBm (100*dBm) */
4299 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4300
4301#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Sushant Kaushik4f640e42014-07-08 12:27:09 +05304302 wiphy->max_remain_on_channel_duration = 5000;
Jeff Johnson295189b2012-06-20 16:38:30 -07004303#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004304
Sunil Duttc69bccb2014-05-26 21:30:20 +05304305 wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands);
4306 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
Rajesh Chauhan98a31f82014-01-06 20:15:25 -08004307 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
4308 wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
4309
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304310 EXIT();
4311 return 0;
4312}
4313
4314/* In this function we are registering wiphy. */
4315int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
4316{
4317 ENTER();
4318 /* Register our wiphy dev with cfg80211 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004319 if (0 > wiphy_register(wiphy))
4320 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304321 /* print error */
Jeff Johnson295189b2012-06-20 16:38:30 -07004322 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
4323 return -EIO;
4324 }
4325
4326 EXIT();
4327 return 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304328}
Jeff Johnson295189b2012-06-20 16:38:30 -07004329
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304330/* In this function we are updating channel list when,
4331 regulatory domain is FCC and country code is US.
4332 Here In FCC standard 5GHz UNII-1 Bands are indoor only.
4333 As per FCC smart phone is not a indoor device.
4334 GO should not opeate on indoor channels */
4335void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy)
4336{
4337 int j;
4338 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4339 tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE;
4340 //Default counrtycode from NV at the time of wiphy initialization.
4341 if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal,
4342 &defaultCountryCode[0]))
4343 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -07004344 hddLog(LOGE, FL("Failed to get default country code from NV"));
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304345 }
4346 if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S'))
4347 {
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05304348 if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ])
4349 {
4350 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ );
4351 return;
4352 }
4353 for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++)
4354 {
4355 struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ];
4356 // Mark UNII -1 band channel as passive
4357 if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq))
4358 band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
4359 }
4360 }
4361}
4362
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05304363/* This function registers for all frame which supplicant is interested in */
4364void wlan_hdd_cfg80211_register_frames(hdd_adapter_t* pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004365{
Jeff Johnson295189b2012-06-20 16:38:30 -07004366 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4367 /* Register for all P2P action, public action etc frames */
4368 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
4369
Jeff Johnsone7245742012-09-05 17:12:55 -07004370 ENTER();
4371
Jeff Johnson295189b2012-06-20 16:38:30 -07004372 /* Right now we are registering these frame when driver is getting
4373 initialized. Once we will move to 2.6.37 kernel, in which we have
4374 frame register ops, we will move this code as a part of that */
4375 /* GAS Initial Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304376 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Jeff Johnson295189b2012-06-20 16:38:30 -07004377 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
4378
4379 /* GAS Initial Response */
4380 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
4381 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304382
Jeff Johnson295189b2012-06-20 16:38:30 -07004383 /* GAS Comeback Request */
4384 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
4385 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
4386
4387 /* GAS Comeback Response */
4388 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
4389 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
4390
4391 /* P2P Public Action */
4392 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304393 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -07004394 P2P_PUBLIC_ACTION_FRAME_SIZE );
4395
4396 /* P2P Action */
4397 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
4398 (v_U8_t*)P2P_ACTION_FRAME,
4399 P2P_ACTION_FRAME_SIZE );
Chet Lanctot186b5732013-03-18 10:26:30 -07004400
Gopichand Nakkalae3d56e72013-04-21 23:33:32 +05304401 /* WNM BSS Transition Request frame */
4402 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
4403 (v_U8_t*)WNM_BSS_ACTION_FRAME,
4404 WNM_BSS_ACTION_FRAME_SIZE );
Leela Venkata Kiran Kumar Reddy Chiralae8e62c82013-10-29 18:23:26 -07004405
4406 /* WNM-Notification */
4407 sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type,
4408 (v_U8_t*)WNM_NOTIFICATION_FRAME,
4409 WNM_NOTIFICATION_FRAME_SIZE );
Jeff Johnson295189b2012-06-20 16:38:30 -07004410}
4411
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05304412void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t* pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07004413{
Jeff Johnson295189b2012-06-20 16:38:30 -07004414 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
4415 /* Register for all P2P action, public action etc frames */
4416 v_U16_t type = (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_ACTION << 4);
4417
Jeff Johnsone7245742012-09-05 17:12:55 -07004418 ENTER();
4419
Jeff Johnson295189b2012-06-20 16:38:30 -07004420 /* Right now we are registering these frame when driver is getting
4421 initialized. Once we will move to 2.6.37 kernel, in which we have
4422 frame register ops, we will move this code as a part of that */
4423 /* GAS Initial Request */
4424
4425 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
4426 (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE );
4427
4428 /* GAS Initial Response */
4429 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
4430 (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304431
Jeff Johnson295189b2012-06-20 16:38:30 -07004432 /* GAS Comeback Request */
4433 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
4434 (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE );
4435
4436 /* GAS Comeback Response */
4437 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
4438 (v_U8_t*)GAS_COMEBACK_RSP, GAS_COMEBACK_RSP_SIZE );
4439
4440 /* P2P Public Action */
4441 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304442 (v_U8_t*)P2P_PUBLIC_ACTION_FRAME,
Jeff Johnson295189b2012-06-20 16:38:30 -07004443 P2P_PUBLIC_ACTION_FRAME_SIZE );
4444
4445 /* P2P Action */
4446 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
4447 (v_U8_t*)P2P_ACTION_FRAME,
4448 P2P_ACTION_FRAME_SIZE );
Leela Venkata Kiran Kumar Reddy Chiralae8e62c82013-10-29 18:23:26 -07004449 /* WNM-Notification */
4450 sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type,
4451 (v_U8_t*)WNM_NOTIFICATION_FRAME,
4452 WNM_NOTIFICATION_FRAME_SIZE );
Jeff Johnson295189b2012-06-20 16:38:30 -07004453}
4454
4455#ifdef FEATURE_WLAN_WAPI
4456void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index,
4457 const u8 *mac_addr, u8 *key , int key_Len)
4458{
4459 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4460 tCsrRoamSetKey setKey;
4461 v_BOOL_t isConnected = TRUE;
4462 int status = 0;
4463 v_U32_t roamId= 0xFF;
4464 tANI_U8 *pKeyPtr = NULL;
4465 int n = 0;
4466
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05304467 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s(%d)",
4468 __func__, hdd_device_modetoString(pAdapter->device_mode),
4469 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004470
Gopichand Nakkalae7480202013-02-11 15:24:22 +05304471 vos_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -07004472 setKey.keyId = key_index; // Store Key ID
4473 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; // SET WAPI Encryption
4474 setKey.keyDirection = eSIR_TX_RX; // Key Directionn both TX and RX
4475 setKey.paeRole = 0 ; // the PAE role
4476 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
4477 {
4478 vos_set_macaddr_broadcast( (v_MACADDR_t *)setKey.peerMac );
4479 }
4480 else
4481 {
4482 isConnected = hdd_connIsConnected(pHddStaCtx);
4483 vos_mem_copy(setKey.peerMac,&pHddStaCtx->conn_info.bssId,WNI_CFG_BSSID_LEN);
4484 }
4485 setKey.keyLength = key_Len;
4486 pKeyPtr = setKey.Key;
4487 memcpy( pKeyPtr, key, key_Len);
4488
Arif Hussain6d2a3322013-11-17 19:50:10 -08004489 hddLog(VOS_TRACE_LEVEL_INFO,"%s: WAPI KEY LENGTH:0x%04x",
Jeff Johnson295189b2012-06-20 16:38:30 -07004490 __func__, key_Len);
4491 for (n = 0 ; n < key_Len; n++)
4492 hddLog(VOS_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
4493 __func__,n,setKey.Key[n]);
4494
4495 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
4496 if ( isConnected )
4497 {
4498 status= sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
4499 pAdapter->sessionId, &setKey, &roamId );
4500 }
4501 if ( status != 0 )
4502 {
4503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4504 "[%4d] sme_RoamSetKey returned ERROR status= %d",
4505 __LINE__, status );
4506 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
4507 }
4508}
4509#endif /* FEATURE_WLAN_WAPI*/
4510
4511#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304512int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07004513 beacon_data_t **ppBeacon,
4514 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004515#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304516int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004517 beacon_data_t **ppBeacon,
4518 struct cfg80211_beacon_data *params,
4519 int dtim_period)
4520#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304521{
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 int size;
4523 beacon_data_t *beacon = NULL;
4524 beacon_data_t *old = NULL;
4525 int head_len,tail_len;
4526
Jeff Johnsone7245742012-09-05 17:12:55 -07004527 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 if (params->head && !params->head_len)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304529 {
4530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4531 FL("head_len is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07004532 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304533 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004534
4535 old = pAdapter->sessionCtx.ap.beacon;
4536
4537 if (!params->head && !old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304538 {
4539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4540 FL("session(%d) old and new heads points to NULL"),
4541 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004542 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304543 }
4544
4545 if (params->tail && !params->tail_len)
4546 {
4547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4548 FL("tail_len is zero but tail is not NULL"));
4549 return -EINVAL;
4550 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004551
Jeff Johnson295189b2012-06-20 16:38:30 -07004552#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38))
4553 /* Kernel 3.0 is not updating dtim_period for set beacon */
4554 if (!params->dtim_period)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304555 {
4556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4557 FL("dtim period is 0"));
Jeff Johnson295189b2012-06-20 16:38:30 -07004558 return -EINVAL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304559 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004560#endif
4561
4562 if(params->head)
4563 head_len = params->head_len;
4564 else
4565 head_len = old->head_len;
4566
4567 if(params->tail || !old)
4568 tail_len = params->tail_len;
4569 else
4570 tail_len = old->tail_len;
4571
4572 size = sizeof(beacon_data_t) + head_len + tail_len;
4573
4574 beacon = kzalloc(size, GFP_KERNEL);
4575
4576 if( beacon == NULL )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304577 {
4578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4579 FL("Mem allocation for beacon failed"));
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 return -ENOMEM;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304581 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004582
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004583#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07004584 if(params->dtim_period || !old )
4585 beacon->dtim_period = params->dtim_period;
4586 else
4587 beacon->dtim_period = old->dtim_period;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004588#else
4589 if(dtim_period || !old )
4590 beacon->dtim_period = dtim_period;
4591 else
4592 beacon->dtim_period = old->dtim_period;
4593#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304594
Jeff Johnson295189b2012-06-20 16:38:30 -07004595 beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t);
4596 beacon->tail = beacon->head + head_len;
4597 beacon->head_len = head_len;
4598 beacon->tail_len = tail_len;
4599
4600 if(params->head) {
4601 memcpy (beacon->head,params->head,beacon->head_len);
4602 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304603 else {
Jeff Johnson295189b2012-06-20 16:38:30 -07004604 if(old)
4605 memcpy (beacon->head,old->head,beacon->head_len);
4606 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304607
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 if(params->tail) {
4609 memcpy (beacon->tail,params->tail,beacon->tail_len);
4610 }
4611 else {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304612 if(old)
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 memcpy (beacon->tail,old->tail,beacon->tail_len);
4614 }
4615
4616 *ppBeacon = beacon;
4617
4618 kfree(old);
4619
4620 return 0;
4621
4622}
Jeff Johnson295189b2012-06-20 16:38:30 -07004623
4624v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid)
4625{
4626 int left = length;
4627 v_U8_t *ptr = pIes;
4628 v_U8_t elem_id,elem_len;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304629
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 while(left >= 2)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304631 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 elem_id = ptr[0];
4633 elem_len = ptr[1];
4634 left -= 2;
4635 if(elem_len > left)
4636 {
4637 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004638 FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
Jeff Johnson295189b2012-06-20 16:38:30 -07004639 eid,elem_len,left);
4640 return NULL;
4641 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304642 if (elem_id == eid)
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 {
4644 return ptr;
4645 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304646
Jeff Johnson295189b2012-06-20 16:38:30 -07004647 left -= elem_len;
4648 ptr += (elem_len + 2);
4649 }
4650 return NULL;
4651}
4652
Jeff Johnson295189b2012-06-20 16:38:30 -07004653/* Check if rate is 11g rate or not */
4654static int wlan_hdd_rate_is_11g(u8 rate)
4655{
Sanjay Devnani28322e22013-06-21 16:13:40 -07004656 static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */
Jeff Johnson295189b2012-06-20 16:38:30 -07004657 u8 i;
4658 for (i = 0; i < 8; i++)
4659 {
4660 if(rate == gRateArray[i])
4661 return TRUE;
4662 }
4663 return FALSE;
4664}
4665
4666/* Check for 11g rate and set proper 11g only mode */
4667static void wlan_hdd_check_11gmode(u8 *pIe, u8* require_ht,
4668 u8* pCheckRatesfor11g, eSapPhyMode* pSapHw_mode)
4669{
4670 u8 i, num_rates = pIe[0];
4671
4672 pIe += 1;
4673 for ( i = 0; i < num_rates; i++)
4674 {
4675 if( *pCheckRatesfor11g && (TRUE == wlan_hdd_rate_is_11g(pIe[i] & RATE_MASK)))
4676 {
4677 /* If rate set have 11g rate than change the mode to 11G */
4678 *pSapHw_mode = eSAP_DOT11_MODE_11g;
4679 if (pIe[i] & BASIC_RATE_MASK)
4680 {
4681 /* If we have 11g rate as basic rate, it means mode
4682 is 11g only mode.
4683 */
4684 *pSapHw_mode = eSAP_DOT11_MODE_11g_ONLY;
4685 *pCheckRatesfor11g = FALSE;
4686 }
4687 }
4688 else if((BASIC_RATE_MASK | WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY) == pIe[i])
4689 {
4690 *require_ht = TRUE;
4691 }
4692 }
4693 return;
4694}
4695
4696static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter)
4697{
4698 tsap_Config_t *pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
4699 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
4700 struct ieee80211_mgmt *pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
4701 u8 checkRatesfor11g = TRUE;
4702 u8 require_ht = FALSE;
4703 u8 *pIe=NULL;
4704
4705 pConfig->SapHw_mode= eSAP_DOT11_MODE_11b;
4706
4707 pIe = wlan_hdd_cfg80211_get_ie_ptr(&pMgmt_frame->u.beacon.variable[0],
4708 pBeacon->head_len, WLAN_EID_SUPP_RATES);
4709 if (pIe != NULL)
4710 {
4711 pIe += 1;
4712 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
4713 &pConfig->SapHw_mode);
4714 }
4715
4716 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
4717 WLAN_EID_EXT_SUPP_RATES);
4718 if (pIe != NULL)
4719 {
4720
4721 pIe += 1;
4722 wlan_hdd_check_11gmode(pIe, &require_ht, &checkRatesfor11g,
4723 &pConfig->SapHw_mode);
4724 }
4725
4726 if( pConfig->channel > 14 )
4727 {
4728 pConfig->SapHw_mode= eSAP_DOT11_MODE_11a;
4729 }
4730
4731 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
4732 WLAN_EID_HT_CAPABILITY);
4733
Gopichand Nakkala747461f2013-04-24 19:24:45 +05304734 if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 {
4736 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n;
4737 if(require_ht)
4738 pConfig->SapHw_mode= eSAP_DOT11_MODE_11n_ONLY;
4739 }
4740}
4741
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304742static int wlan_hdd_add_ie(hdd_adapter_t* pHostapdAdapter, v_U8_t *genie,
4743 v_U8_t *total_ielen, v_U8_t *oui, v_U8_t oui_size)
4744{
Arif Hussaine7f3ea52013-09-12 21:56:36 -07004745 v_U16_t ielen = 0;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304746 v_U8_t *pIe = NULL;
4747 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
4748
4749 pIe = wlan_hdd_get_vendor_oui_ie_ptr(oui, oui_size,
4750 pBeacon->tail, pBeacon->tail_len);
4751
4752 if (pIe)
4753 {
4754 ielen = pIe[1] + 2;
4755 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
4756 {
4757 vos_mem_copy(&genie[*total_ielen], pIe, ielen);
4758 }
4759 else
4760 {
4761 hddLog( VOS_TRACE_LEVEL_ERROR, "**Ie Length is too big***");
4762 return -EINVAL;
4763 }
4764 *total_ielen += ielen;
4765 }
4766 return 0;
4767}
4768
Arif Hussaine7f3ea52013-09-12 21:56:36 -07004769static void wlan_hdd_add_hostapd_conf_vsie(hdd_adapter_t* pHostapdAdapter,
4770 v_U8_t *genie, v_U8_t *total_ielen)
4771{
4772 beacon_data_t *pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
4773 int left = pBeacon->tail_len;
4774 v_U8_t *ptr = pBeacon->tail;
4775 v_U8_t elem_id, elem_len;
4776 v_U16_t ielen = 0;
4777
4778 if ( NULL == ptr || 0 == left )
4779 return;
4780
4781 while (left >= 2)
4782 {
4783 elem_id = ptr[0];
4784 elem_len = ptr[1];
4785 left -= 2;
4786 if (elem_len > left)
4787 {
4788 hddLog( VOS_TRACE_LEVEL_ERROR,
4789 "****Invalid IEs eid = %d elem_len=%d left=%d*****",
4790 elem_id, elem_len, left);
4791 return;
4792 }
4793 if (IE_EID_VENDOR == elem_id)
4794 {
4795 /* skipping the VSIE's which we don't want to include or
4796 * it will be included by existing code
4797 */
4798 if ((memcmp( &ptr[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) != 0 ) &&
4799#ifdef WLAN_FEATURE_WFD
4800 (memcmp( &ptr[2], WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE) != 0) &&
4801#endif
4802 (memcmp( &ptr[2], WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
4803 (memcmp( &ptr[2], BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
4804 (memcmp( &ptr[2], "\x00\x50\xf2\x02", WPA_OUI_TYPE_SIZE) != 0) &&
4805 (memcmp( &ptr[2], WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE) != 0) &&
4806 (memcmp( &ptr[2], P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE) != 0))
4807 {
4808 ielen = ptr[1] + 2;
4809 if ((*total_ielen + ielen) <= MAX_GENIE_LEN)
4810 {
4811 vos_mem_copy(&genie[*total_ielen], ptr, ielen);
4812 *total_ielen += ielen;
4813 }
4814 else
4815 {
4816 hddLog( VOS_TRACE_LEVEL_ERROR,
4817 "IE Length is too big "
4818 "IEs eid=%d elem_len=%d total_ie_lent=%d",
4819 elem_id, elem_len, *total_ielen);
4820 }
4821 }
4822 }
4823
4824 left -= elem_len;
4825 ptr += (elem_len + 2);
4826 }
4827 return;
4828}
4829
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004830#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07004831static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
4832 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07004833#else
4834static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter,
4835 struct cfg80211_beacon_data *params)
4836#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004837{
4838 v_U8_t *genie;
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304839 v_U8_t total_ielen = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 v_U8_t addIE[1] = {0};
Jeff Johnsone7245742012-09-05 17:12:55 -07004841 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004842
4843 genie = vos_mem_malloc(MAX_GENIE_LEN);
4844
4845 if(genie == NULL) {
4846
4847 return -ENOMEM;
4848 }
4849
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304850 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
4851 &total_ielen, WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07004852 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304853 hddLog(LOGE,
4854 FL("Adding WPS IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304855 ret = -EINVAL;
4856 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 }
4858
4859#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304860 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
4861 &total_ielen, WFD_OUI_TYPE, WFD_OUI_TYPE_SIZE))
4862 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304863 hddLog(LOGE,
4864 FL("Adding WFD IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304865 ret = -EINVAL;
4866 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004867 }
4868#endif
4869
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304870 if (0 != wlan_hdd_add_ie(pHostapdAdapter, genie,
4871 &total_ielen, P2P_OUI_TYPE, P2P_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07004872 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304873 hddLog(LOGE,
4874 FL("Adding P2P IE failed"));
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05304875 ret = -EINVAL;
4876 goto done;
4877 }
4878
4879 if (WLAN_HDD_SOFTAP == pHostapdAdapter->device_mode)
4880 {
Arif Hussaine7f3ea52013-09-12 21:56:36 -07004881 wlan_hdd_add_hostapd_conf_vsie(pHostapdAdapter, genie, &total_ielen);
Jeff Johnson295189b2012-06-20 16:38:30 -07004882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004883
4884 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4885 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie, total_ielen, NULL,
4886 eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
4887 {
4888 hddLog(LOGE,
4889 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07004890 ret = -EINVAL;
4891 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 }
4893
4894 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4895 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
4896 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
4897 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
4898 ==eHAL_STATUS_FAILURE)
4899 {
4900 hddLog(LOGE,
4901 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07004902 ret = -EINVAL;
4903 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004904 }
4905
4906 // Added for ProResp IE
4907 if ( (params->proberesp_ies != NULL) && (params->proberesp_ies_len != 0) )
4908 {
4909 u16 rem_probe_resp_ie_len = params->proberesp_ies_len;
4910 u8 probe_rsp_ie_len[3] = {0};
4911 u8 counter = 0;
4912 /* Check Probe Resp Length if it is greater then 255 then Store
4913 Probe Resp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1 &
4914 WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are not able
4915 Store More then 255 bytes into One Variable.
4916 */
4917 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
4918 {
4919 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
4920 {
4921 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
4922 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
4923 }
4924 else
4925 {
4926 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
4927 rem_probe_resp_ie_len = 0;
4928 }
4929 }
4930
4931 rem_probe_resp_ie_len = 0;
4932
4933 if (probe_rsp_ie_len[0] > 0)
4934 {
4935 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4936 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
4937 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
4938 probe_rsp_ie_len[0], NULL,
4939 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
4940 {
4941 hddLog(LOGE,
4942 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07004943 ret = -EINVAL;
4944 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004945 }
4946 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
4947 }
4948
4949 if (probe_rsp_ie_len[1] > 0)
4950 {
4951 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4952 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
4953 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
4954 probe_rsp_ie_len[1], NULL,
4955 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
4956 {
4957 hddLog(LOGE,
4958 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07004959 ret = -EINVAL;
4960 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 }
4962 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
4963 }
4964
4965 if (probe_rsp_ie_len[2] > 0)
4966 {
4967 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4968 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
4969 (tANI_U8*)&params->proberesp_ies[rem_probe_resp_ie_len],
4970 probe_rsp_ie_len[2], NULL,
4971 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
4972 {
4973 hddLog(LOGE,
4974 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07004975 ret = -EINVAL;
4976 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07004977 }
4978 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
4979 }
4980
4981 if (probe_rsp_ie_len[1] == 0 )
4982 {
4983 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4984 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
4985 eANI_BOOLEAN_FALSE) )
4986 {
4987 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004988 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07004989 }
4990 }
4991
4992 if (probe_rsp_ie_len[2] == 0 )
4993 {
4994 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
4995 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
4996 eANI_BOOLEAN_FALSE) )
4997 {
4998 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08004999 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07005000 }
5001 }
5002
5003 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5004 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5005 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
5006 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
5007 == eHAL_STATUS_FAILURE)
5008 {
5009 hddLog(LOGE,
5010 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07005011 ret = -EINVAL;
5012 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07005013 }
5014 }
5015 else
5016 {
5017 // Reset WNI_CFG_PROBE_RSP Flags
5018 wlan_hdd_reset_prob_rspies(pHostapdAdapter);
5019
5020 hddLog(VOS_TRACE_LEVEL_INFO,
5021 "%s: No Probe Response IE received in set beacon",
5022 __func__);
5023 }
5024
5025 // Added for AssocResp IE
5026 if ( (params->assocresp_ies != NULL) && (params->assocresp_ies_len != 0) )
5027 {
5028 if (ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5029 WNI_CFG_ASSOC_RSP_ADDNIE_DATA, (tANI_U8*)params->assocresp_ies,
5030 params->assocresp_ies_len, NULL,
5031 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5032 {
5033 hddLog(LOGE,
5034 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_DATA to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07005035 ret = -EINVAL;
5036 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07005037 }
5038
5039 if (ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5040 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 1, NULL,
5041 test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags) ?
5042 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE)
5043 == eHAL_STATUS_FAILURE)
5044 {
5045 hddLog(LOGE,
5046 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnsone7245742012-09-05 17:12:55 -07005047 ret = -EINVAL;
5048 goto done;
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 }
5050 }
5051 else
5052 {
5053 hddLog(VOS_TRACE_LEVEL_INFO,
5054 "%s: No Assoc Response IE received in set beacon",
5055 __func__);
5056
5057 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5058 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5059 eANI_BOOLEAN_FALSE) )
5060 {
5061 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005062 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07005063 }
5064 }
5065
Jeff Johnsone7245742012-09-05 17:12:55 -07005066done:
Jeff Johnson295189b2012-06-20 16:38:30 -07005067 vos_mem_free(genie);
Gopichand Nakkala2b25f4e2013-03-21 19:14:07 +05305068 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005069}
Jeff Johnson295189b2012-06-20 16:38:30 -07005070
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305071/*
Jeff Johnson295189b2012-06-20 16:38:30 -07005072 * FUNCTION: wlan_hdd_validate_operation_channel
5073 * called by wlan_hdd_cfg80211_start_bss() and
5074 * wlan_hdd_cfg80211_set_channel()
5075 * This function validates whether given channel is part of valid
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305076 * channel list.
5077 */
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005078VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel)
Jeff Johnson295189b2012-06-20 16:38:30 -07005079{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305080
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 v_U32_t num_ch = 0;
5082 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5083 u32 indx = 0;
5084 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05305085 v_U8_t fValidChannel = FALSE, count = 0;
5086 hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305087
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5089
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05305090 if ( hdd_pConfig_ini->sapAllowAllChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07005091 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05305092 /* Validate the channel */
5093 for (count = RF_CHAN_1 ; count <= RF_CHAN_165 ; count++)
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05305095 if ( channel == rfChannels[count].channelNum )
5096 {
5097 fValidChannel = TRUE;
5098 break;
5099 }
5100 }
5101 if (fValidChannel != TRUE)
5102 {
5103 hddLog(VOS_TRACE_LEVEL_ERROR,
5104 "%s: Invalid Channel [%d]", __func__, channel);
5105 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005106 }
5107 }
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05305108 else
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 {
Madan Mohan Koyylamudi64267f72013-02-05 14:07:08 +05305110 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5111 valid_ch, &num_ch))
5112 {
5113 hddLog(VOS_TRACE_LEVEL_ERROR,
5114 "%s: failed to get valid channel list", __func__);
5115 return VOS_STATUS_E_FAILURE;
5116 }
5117 for (indx = 0; indx < num_ch; indx++)
5118 {
5119 if (channel == valid_ch[indx])
5120 {
5121 break;
5122 }
5123 }
5124
Rashmi Ramanna3b59e122014-04-10 14:45:13 +05305125 if (indx >= num_ch)
5126 {
5127 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5128 {
5129 eCsrBand band;
5130 unsigned int freq;
5131
5132 sme_GetFreqBand(hHal, &band);
5133
5134 if (eCSR_BAND_5G == band)
5135 {
5136#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
5137 if (channel <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
5138 {
5139 freq = ieee80211_channel_to_frequency(channel,
5140 IEEE80211_BAND_2GHZ);
5141 }
5142 else
5143 {
5144 freq = ieee80211_channel_to_frequency(channel,
5145 IEEE80211_BAND_5GHZ);
5146 }
5147#else
5148 freq = ieee80211_channel_to_frequency(channel);
5149#endif
5150 if(WLAN_HDD_IS_SOCIAL_CHANNEL(freq))
5151 return VOS_STATUS_SUCCESS;
5152 }
5153 }
5154
5155 hddLog(VOS_TRACE_LEVEL_ERROR,
5156 "%s: Invalid Channel [%d]", __func__, channel);
5157 return VOS_STATUS_E_FAILURE;
5158 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 }
Rashmi Ramanna3b59e122014-04-10 14:45:13 +05305160
Jeff Johnson295189b2012-06-20 16:38:30 -07005161 return VOS_STATUS_SUCCESS;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305162
Jeff Johnson295189b2012-06-20 16:38:30 -07005163}
5164
Viral Modi3a32cc52013-02-08 11:14:52 -08005165/**
5166 * FUNCTION: wlan_hdd_cfg80211_set_channel
5167 * This function is used to set the channel number
5168 */
5169static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device *dev,
5170 struct ieee80211_channel *chan,
5171 enum nl80211_channel_type channel_type
5172 )
5173{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305174 hdd_adapter_t *pAdapter = NULL;
Viral Modi3a32cc52013-02-08 11:14:52 -08005175 v_U32_t num_ch = 0;
Jeff Johnson4416a782013-03-25 14:17:50 -07005176 int channel = 0;
Viral Modi3a32cc52013-02-08 11:14:52 -08005177 int freq = chan->center_freq; /* freq is in MHZ */
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305178 hdd_context_t *pHddCtx;
5179 int status;
Viral Modi3a32cc52013-02-08 11:14:52 -08005180
5181 ENTER();
5182
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305183
Viral Modi3a32cc52013-02-08 11:14:52 -08005184 if( NULL == dev )
5185 {
5186 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005187 "%s: Called with dev = NULL.", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08005188 return -ENODEV;
5189 }
5190 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305191
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305192 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
5193 TRACE_CODE_HDD_CFG80211_SET_CHANNEL, pAdapter->sessionId,
5194 channel_type ));
Viral Modi3a32cc52013-02-08 11:14:52 -08005195 hddLog(VOS_TRACE_LEVEL_INFO,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05305196 "%s: device_mode = %s (%d) freq = %d", __func__,
5197 hdd_device_modetoString(pAdapter->device_mode),
5198 pAdapter->device_mode, chan->center_freq);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305199
5200 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5201 status = wlan_hdd_validate_context(pHddCtx);
5202
5203 if (0 != status)
Viral Modi3a32cc52013-02-08 11:14:52 -08005204 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5206 "%s: HDD context is not valid", __func__);
5207 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08005208 }
5209
5210 /*
5211 * Do freq to chan conversion
5212 * TODO: for 11a
5213 */
5214
5215 channel = ieee80211_frequency_to_channel(freq);
5216
5217 /* Check freq range */
5218 if ((WNI_CFG_CURRENT_CHANNEL_STAMIN > channel) ||
5219 (WNI_CFG_CURRENT_CHANNEL_STAMAX < channel))
5220 {
5221 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005222 "%s: Channel [%d] is outside valid range from %d to %d",
Viral Modi3a32cc52013-02-08 11:14:52 -08005223 __func__, channel, WNI_CFG_CURRENT_CHANNEL_STAMIN,
5224 WNI_CFG_CURRENT_CHANNEL_STAMAX);
5225 return -EINVAL;
5226 }
5227
5228 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5229
Gopichand Nakkala6ab19562013-03-07 13:59:42 +05305230 if ((WLAN_HDD_SOFTAP != pAdapter->device_mode) &&
5231 (WLAN_HDD_P2P_GO != pAdapter->device_mode))
Viral Modi3a32cc52013-02-08 11:14:52 -08005232 {
5233 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pAdapter,channel))
5234 {
5235 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005236 "%s: Invalid Channel [%d]", __func__, channel);
Viral Modi3a32cc52013-02-08 11:14:52 -08005237 return -EINVAL;
5238 }
5239 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
5240 "%s: set channel to [%d] for device mode =%d",
5241 __func__, channel,pAdapter->device_mode);
5242 }
5243 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Viral Modi3a32cc52013-02-08 11:14:52 -08005244 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Viral Modi3a32cc52013-02-08 11:14:52 -08005245 )
5246 {
5247 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5248 tCsrRoamProfile * pRoamProfile = &pWextState->roamProfile;
5249 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5250
5251 if (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)
5252 {
5253 /* Link is up then return cant set channel*/
5254 hddLog( VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005255 "%s: IBSS Associated, can't set the channel", __func__);
Viral Modi3a32cc52013-02-08 11:14:52 -08005256 return -EINVAL;
5257 }
5258
5259 num_ch = pRoamProfile->ChannelInfo.numOfChannels = 1;
5260 pHddStaCtx->conn_info.operationChannel = channel;
5261 pRoamProfile->ChannelInfo.ChannelList =
5262 &pHddStaCtx->conn_info.operationChannel;
5263 }
5264 else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Viral Modi3a32cc52013-02-08 11:14:52 -08005265 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Viral Modi3a32cc52013-02-08 11:14:52 -08005266 )
5267 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05305268 if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
5269 {
5270 if(VOS_STATUS_SUCCESS !=
5271 wlan_hdd_validate_operation_channel(pAdapter,channel))
5272 {
5273 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005274 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05305275 return -EINVAL;
5276 }
5277 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
5278 }
5279 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
Viral Modi3a32cc52013-02-08 11:14:52 -08005280 {
5281 hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
5282
5283 /* If auto channel selection is configured as enable/ 1 then ignore
5284 channel set by supplicant
5285 */
5286 if ( cfg_param->apAutoChannelSelection )
5287 {
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05305288 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel =
5289 AUTO_CHANNEL_SELECT;
Viral Modi3a32cc52013-02-08 11:14:52 -08005290 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05305291 "%s: set channel to auto channel (0) for device mode =%s (%d)",
5292 __func__, hdd_device_modetoString(pAdapter->device_mode),
5293 pAdapter->device_mode);
Viral Modi3a32cc52013-02-08 11:14:52 -08005294 }
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05305295 else
5296 {
5297 if(VOS_STATUS_SUCCESS !=
5298 wlan_hdd_validate_operation_channel(pAdapter,channel))
5299 {
5300 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005301 "%s: Invalid Channel [%d]", __func__, channel);
Gopichand Nakkalac8fa7b62013-03-11 13:56:41 +05305302 return -EINVAL;
5303 }
5304 (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->sapConfig.channel = channel;
5305 }
Viral Modi3a32cc52013-02-08 11:14:52 -08005306 }
5307 }
5308 else
5309 {
5310 hddLog(VOS_TRACE_LEVEL_FATAL,
5311 "%s: Invalid device mode failed to set valid channel", __func__);
5312 return -EINVAL;
5313 }
5314 EXIT();
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305315 return status;
Viral Modi3a32cc52013-02-08 11:14:52 -08005316}
5317
Jeff Johnson295189b2012-06-20 16:38:30 -07005318#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5319static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
5320 struct beacon_parameters *params)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005321#else
5322static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
5323 struct cfg80211_beacon_data *params,
5324 const u8 *ssid, size_t ssid_len,
5325 enum nl80211_hidden_ssid hidden_ssid)
5326#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005327{
5328 tsap_Config_t *pConfig;
5329 beacon_data_t *pBeacon = NULL;
5330 struct ieee80211_mgmt *pMgmt_frame;
5331 v_U8_t *pIe=NULL;
5332 v_U16_t capab_info;
5333 eCsrAuthType RSNAuthType;
5334 eCsrEncryptionType RSNEncryptType;
5335 eCsrEncryptionType mcRSNEncryptType;
5336 int status = VOS_STATUS_SUCCESS;
5337 tpWLAN_SAPEventCB pSapEventCallback;
5338 hdd_hostapd_state_t *pHostapdState;
5339 v_U8_t wpaRsnIEdata[(SIR_MAC_MAX_IE_LENGTH * 2)+4]; //Max ie length 255 * 2(WPA+RSN) + 2 bytes (vendor specific ID) * 2
5340 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext;
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05305341 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005342 struct qc_mac_acl_entry *acl_entry = NULL;
Siddharth Bhal5cba24e2014-05-08 18:59:39 +05305343 hdd_config_t *iniConfig;
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 v_SINT_t i;
Madan Mohan Koyyalamudi543172b2012-12-05 16:40:18 -08005345 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
Chet Lanctot40142442014-05-20 13:39:25 -07005346 v_BOOL_t MFPCapable = VOS_FALSE;
5347 v_BOOL_t MFPRequired = VOS_FALSE;
Abhishek Singhf0ac1752014-03-05 17:47:09 +05305348 eHddDot11Mode sapDot11Mode =
5349 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->sapDot11Mode;
Jeff Johnson295189b2012-06-20 16:38:30 -07005350
5351 ENTER();
5352
Siddharth Bhal5cba24e2014-05-08 18:59:39 +05305353 iniConfig = pHddCtx->cfg_ini;
5354
Jeff Johnson295189b2012-06-20 16:38:30 -07005355 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter);
5356
5357 pConfig = &pHostapdAdapter->sessionCtx.ap.sapConfig;
5358
5359 pBeacon = pHostapdAdapter->sessionCtx.ap.beacon;
5360
5361 pMgmt_frame = (struct ieee80211_mgmt*)pBeacon->head;
5362
5363 pConfig->beacon_int = pMgmt_frame->u.beacon.beacon_int;
5364
5365 //channel is already set in the set_channel Call back
5366 //pConfig->channel = pCommitConfig->channel;
5367
5368 /*Protection parameter to enable or disable*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305369 pConfig->protEnabled =
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled;
5371
5372 pConfig->dtim_period = pBeacon->dtim_period;
5373
Arif Hussain6d2a3322013-11-17 19:50:10 -08005374 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"****pConfig->dtim_period=%d***",
Jeff Johnson295189b2012-06-20 16:38:30 -07005375 pConfig->dtim_period);
5376
5377
Madan Mohan Koyyalamudie0ca11f2012-11-27 15:57:52 -08005378 if (pHostapdAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson32d95a32012-09-10 13:15:23 -07005379 {
5380 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 WLAN_EID_COUNTRY);
Kiet Lam083504c2013-11-25 14:17:45 +05305382 if(memcmp(pHddCtx->cfg_ini->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0)
5383 {
5384 tANI_BOOLEAN restartNeeded;
5385 pConfig->ieee80211d = 1;
5386 vos_mem_copy(pConfig->countryCode, pHddCtx->cfg_ini->apCntryCode, 3);
5387 sme_setRegInfo(hHal, pConfig->countryCode);
5388 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
5389 }
5390 else if(pIe)
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 {
Jeff Johnson32d95a32012-09-10 13:15:23 -07005392 tANI_BOOLEAN restartNeeded;
Jeff Johnson32d95a32012-09-10 13:15:23 -07005393 pConfig->ieee80211d = 1;
5394 vos_mem_copy(pConfig->countryCode, &pIe[2], 3);
5395 sme_setRegInfo(hHal, pConfig->countryCode);
5396 sme_ResetCountryCodeInformation(hHal, &restartNeeded);
Jeff Johnson295189b2012-06-20 16:38:30 -07005397 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07005398 else
5399 {
5400 pConfig->ieee80211d = 0;
5401 }
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05305402 /*
5403 * If auto channel is configured i.e. channel is 0,
5404 * so skip channel validation.
5405 */
5406 if( AUTO_CHANNEL_SELECT != pConfig->channel )
5407 {
5408 if(VOS_STATUS_SUCCESS != wlan_hdd_validate_operation_channel(pHostapdAdapter,pConfig->channel))
5409 {
5410 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005411 "%s: Invalid Channel [%d]", __func__, pConfig->channel);
Madan Mohan Koyylamudia16d0202013-02-01 11:05:57 +05305412 return -EINVAL;
5413 }
5414 }
5415 else
5416 {
5417 if(1 != pHddCtx->is_dynamic_channel_range_set)
5418 {
5419 hdd_config_t *hdd_pConfig= (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini;
5420 WLANSAP_SetChannelRange(hHal, hdd_pConfig->apStartChannelNum,
5421 hdd_pConfig->apEndChannelNum,hdd_pConfig->apOperatingBand);
5422 }
5423 pHddCtx->is_dynamic_channel_range_set = 0;
5424 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07005426 else
Jeff Johnson295189b2012-06-20 16:38:30 -07005427 {
5428 pConfig->ieee80211d = 0;
5429 }
5430 pConfig->authType = eSAP_AUTO_SWITCH;
5431
5432 capab_info = pMgmt_frame->u.beacon.capab_info;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305433
5434 pConfig->privacy = (pMgmt_frame->u.beacon.capab_info &
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE;
5436
5437 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy;
5438
5439 /*Set wps station to configured*/
5440 pIe = wlan_hdd_get_wps_ie_ptr(pBeacon->tail, pBeacon->tail_len);
5441
5442 if(pIe)
5443 {
5444 if(pIe[1] < (2 + WPS_OUI_TYPE_SIZE))
5445 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08005446 hddLog( VOS_TRACE_LEVEL_ERROR, "**Wps Ie Length is too small***");
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 return -EINVAL;
5448 }
5449 else if(memcmp(&pIe[2], WPS_OUI_TYPE, WPS_OUI_TYPE_SIZE) == 0)
5450 {
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005451 hddLog( VOS_TRACE_LEVEL_INFO, "** WPS IE(len %d) ***", (pIe[1]+2));
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 /* Check 15 bit of WPS IE as it contain information for wps state
5453 * WPS state
5454 */
5455 if(SAP_WPS_ENABLED_UNCONFIGURED == pIe[15])
5456 {
5457 pConfig->wps_state = SAP_WPS_ENABLED_UNCONFIGURED;
5458 } else if(SAP_WPS_ENABLED_CONFIGURED == pIe[15])
5459 {
5460 pConfig->wps_state = SAP_WPS_ENABLED_CONFIGURED;
5461 }
5462 }
5463 }
5464 else
5465 {
5466 pConfig->wps_state = SAP_WPS_DISABLED;
5467 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305468 pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up
Jeff Johnson295189b2012-06-20 16:38:30 -07005469
c_hpothufe599e92014-06-16 11:38:55 +05305470 pConfig->RSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
5471 pConfig->mcRSNEncryptType = eCSR_ENCRYPT_TYPE_NONE;
5472 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType =
5473 eCSR_ENCRYPT_TYPE_NONE;
5474
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 pConfig->RSNWPAReqIELength = 0;
5476 pConfig->pRSNWPAReqIE = NULL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305477 pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len,
Jeff Johnson295189b2012-06-20 16:38:30 -07005478 WLAN_EID_RSN);
5479 if(pIe && pIe[1])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305480 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005481 pConfig->RSNWPAReqIELength = pIe[1] + 2;
5482 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
5483 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305484 /* The actual processing may eventually be more extensive than
5485 * this. Right now, just consume any PMKIDs that are sent in
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 * by the app.
5487 * */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305488 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07005489 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
5490 &RSNEncryptType,
5491 &mcRSNEncryptType,
5492 &RSNAuthType,
Chet Lanctot8cecea22014-02-11 19:09:36 -08005493 &MFPCapable,
5494 &MFPRequired,
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 pConfig->pRSNWPAReqIE[1]+2,
5496 pConfig->pRSNWPAReqIE );
5497
5498 if( VOS_STATUS_SUCCESS == status )
5499 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305500 /* Now copy over all the security attributes you have
5501 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 * */
5503 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
5504 pConfig->mcRSNEncryptType = mcRSNEncryptType;
5505 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
5506 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305507 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08005508 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
5510 }
5511 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305512
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE,
5514 pBeacon->tail, pBeacon->tail_len);
5515
5516 if(pIe && pIe[1] && (pIe[0] == DOT11F_EID_WPA))
5517 {
5518 if (pConfig->pRSNWPAReqIE)
5519 {
5520 /*Mixed mode WPA/WPA2*/
5521 memcpy((&wpaRsnIEdata[0] + pConfig->RSNWPAReqIELength), pIe, pIe[1] + 2);
5522 pConfig->RSNWPAReqIELength += pIe[1] + 2;
5523 }
5524 else
5525 {
5526 pConfig->RSNWPAReqIELength = pIe[1] + 2;
5527 memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength);
5528 pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305529 status = hdd_softap_unpackIE(
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 vos_get_context( VOS_MODULE_ID_SME, pVosContext),
5531 &RSNEncryptType,
5532 &mcRSNEncryptType,
5533 &RSNAuthType,
Chet Lanctot8cecea22014-02-11 19:09:36 -08005534 &MFPCapable,
5535 &MFPRequired,
Jeff Johnson295189b2012-06-20 16:38:30 -07005536 pConfig->pRSNWPAReqIE[1]+2,
5537 pConfig->pRSNWPAReqIE );
5538
5539 if( VOS_STATUS_SUCCESS == status )
5540 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305541 /* Now copy over all the security attributes you have
5542 * parsed out
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 * */
5544 pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE
5545 pConfig->mcRSNEncryptType = mcRSNEncryptType;
5546 (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType
5547 = RSNEncryptType;
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305548 hddLog( LOG1, FL("CSR AuthType = %d, "
Arif Hussain6d2a3322013-11-17 19:50:10 -08005549 "EncryptionType = %d mcEncryptionType = %d"),
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 RSNAuthType, RSNEncryptType, mcRSNEncryptType);
5551 }
5552 }
5553 }
5554
Jeff Johnson4416a782013-03-25 14:17:50 -07005555 if (pConfig->RSNWPAReqIELength > sizeof wpaRsnIEdata) {
5556 hddLog( VOS_TRACE_LEVEL_ERROR, "**RSNWPAReqIELength is too large***");
5557 return -EINVAL;
5558 }
5559
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 pConfig->SSIDinfo.ssidHidden = VOS_FALSE;
5561
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005562#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 if (params->ssid != NULL)
5564 {
5565 memcpy(pConfig->SSIDinfo.ssid.ssId, params->ssid, params->ssid_len);
5566 pConfig->SSIDinfo.ssid.length = params->ssid_len;
5567 if (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
5568 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
5569 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005570#else
5571 if (ssid != NULL)
5572 {
5573 memcpy(pConfig->SSIDinfo.ssid.ssId, ssid, ssid_len);
5574 pConfig->SSIDinfo.ssid.length = ssid_len;
5575 if (hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
5576 pConfig->SSIDinfo.ssidHidden = VOS_TRUE;
5577 }
5578#endif
5579
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305580 vos_mem_copy(pConfig->self_macaddr.bytes,
Jeff Johnson295189b2012-06-20 16:38:30 -07005581 pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t));
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305582
Jeff Johnson295189b2012-06-20 16:38:30 -07005583 /* default value */
5584 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
5585 pConfig->num_accept_mac = 0;
5586 pConfig->num_deny_mac = 0;
5587
5588 pIe = wlan_hdd_get_vendor_oui_ie_ptr(BLACKLIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
5589 pBeacon->tail, pBeacon->tail_len);
5590
5591 /* pIe for black list is following form:
5592 type : 1 byte
5593 length : 1 byte
5594 OUI : 4 bytes
5595 acl type : 1 byte
5596 no of mac addr in black list: 1 byte
5597 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305598 */
5599 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07005600 {
5601 pConfig->SapMacaddr_acl = pIe[6];
5602 pConfig->num_deny_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08005603 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005604 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05305605 if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS)
5606 pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
5608 for (i = 0; i < pConfig->num_deny_mac; i++)
5609 {
5610 vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr));
5611 acl_entry++;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305612 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005613 }
5614 pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE,
5615 pBeacon->tail, pBeacon->tail_len);
5616
5617 /* pIe for white list is following form:
5618 type : 1 byte
5619 length : 1 byte
5620 OUI : 4 bytes
5621 acl type : 1 byte
5622 no of mac addr in white list: 1 byte
5623 list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305624 */
5625 if ((pIe != NULL) && (pIe[1] != 0))
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 {
5627 pConfig->SapMacaddr_acl = pIe[6];
5628 pConfig->num_accept_mac = pIe[7];
Arif Hussain6d2a3322013-11-17 19:50:10 -08005629 hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 pIe[6], pIe[7]);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05305631 if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS)
5632 pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07005633 acl_entry = (struct qc_mac_acl_entry *)(pIe + 8);
5634 for (i = 0; i < pConfig->num_accept_mac; i++)
5635 {
5636 vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(qcmacaddr));
5637 acl_entry++;
5638 }
5639 }
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +05305640
Jeff Johnson295189b2012-06-20 16:38:30 -07005641 wlan_hdd_set_sapHwmode(pHostapdAdapter);
5642
Jeff Johnsone7245742012-09-05 17:12:55 -07005643#ifdef WLAN_FEATURE_11AC
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08005644 /* Overwrite the hostapd setting for HW mode only for 11ac.
Kiet Lam0f320422013-11-21 19:29:17 +05305645 * This is valid only if mode is set to 11n in hostapd, either AUTO or
5646 * 11ac in .ini and 11ac is supported by both host and firmware.
5647 * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode)
5648 */
Ravi Kumar Vaishnavbbaebbe2013-01-15 17:09:48 -08005649 if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) ||
5650 (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) &&
Abhishek Singhf0ac1752014-03-05 17:47:09 +05305651 (( sapDot11Mode == eHDD_DOT11_MODE_AUTO ) ||
5652 ( sapDot11Mode == eHDD_DOT11_MODE_11ac ) ||
5653 ( sapDot11Mode == eHDD_DOT11_MODE_11ac_ONLY ) ) &&
5654 (sme_IsFeatureSupportedByDriver(DOT11AC)) &&
5655 (sme_IsFeatureSupportedByFW(DOT11AC)) )
Jeff Johnsone7245742012-09-05 17:12:55 -07005656 {
Siddharth Bhalf42f8592014-05-15 13:39:07 +05305657 v_U32_t operatingBand = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07005658 pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac;
Siddharth Bhalf42f8592014-05-15 13:39:07 +05305659 ccmCfgGetInt(hHal, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, &operatingBand);
Ravi Joshi83bfaa12013-05-28 22:12:08 -07005660
Siddharth Bhal5cba24e2014-05-08 18:59:39 +05305661 /* If ACS disable and selected channel <= 14
5662 * OR
5663 * ACS enabled and ACS operating band is choosen as 2.4
5664 * AND
5665 * VHT in 2.4G Disabled
5666 * THEN
5667 * Fallback to 11N mode
5668 */
5669 if (((AUTO_CHANNEL_SELECT != pConfig->channel && pConfig->channel <= SIR_11B_CHANNEL_END)
5670 || (AUTO_CHANNEL_SELECT == pConfig->channel &&
Siddharth Bhalf42f8592014-05-15 13:39:07 +05305671 operatingBand == RF_SUBBAND_2_4_GHZ)) &&
Siddharth Bhal5cba24e2014-05-08 18:59:39 +05305672 iniConfig->enableVhtFor24GHzBand == FALSE)
Ravi Joshi83bfaa12013-05-28 22:12:08 -07005673 {
Siddharth Bhalf42f8592014-05-15 13:39:07 +05305674 hddLog(LOGW, FL("Setting hwmode to 11n, operatingBand = %d, Channel = %d"),
5675 operatingBand, pConfig->channel);
Ravi Joshi83bfaa12013-05-28 22:12:08 -07005676 pConfig->SapHw_mode = eSAP_DOT11_MODE_11n;
5677 }
Jeff Johnsone7245742012-09-05 17:12:55 -07005678 }
5679#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305680
Ravi Joshiaeb7d9e2013-05-02 12:28:14 -07005681 if ( AUTO_CHANNEL_SELECT != pConfig->channel )
5682 {
5683 sme_SelectCBMode(hHal,
5684 sapConvertSapPhyModeToCsrPhyMode(pConfig->SapHw_mode),
5685 pConfig->channel);
5686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005687 // ht_capab is not what the name conveys,this is used for protection bitmap
5688 pConfig->ht_capab =
5689 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection;
5690
5691 if ( 0 != wlan_hdd_cfg80211_update_apies(pHostapdAdapter, params) )
5692 {
5693 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
5694 return -EINVAL;
5695 }
5696
5697 //Uapsd Enabled Bit
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305698 pConfig->UapsdEnable =
Jeff Johnson295189b2012-06-20 16:38:30 -07005699 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled;
5700 //Enable OBSS protection
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305701 pConfig->obssProtEnabled =
5702 (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled;
Jeff Johnson295189b2012-06-20 16:38:30 -07005703
Chet Lanctot8cecea22014-02-11 19:09:36 -08005704#ifdef WLAN_FEATURE_11W
5705 pConfig->mfpCapable = MFPCapable;
5706 pConfig->mfpRequired = MFPRequired;
5707 hddLog(LOGW, FL("Soft AP MFP capable %d, MFP required %d\n"),
5708 pConfig->mfpCapable, pConfig->mfpRequired);
5709#endif
5710
Arif Hussain6d2a3322013-11-17 19:50:10 -08005711 hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR),
Jeff Johnson295189b2012-06-20 16:38:30 -07005712 MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes));
Arif Hussain6d2a3322013-11-17 19:50:10 -08005713 hddLog(LOGW,FL("ssid =%s, beaconint=%d, channel=%d"),
5714 pConfig->SSIDinfo.ssid.ssId, (int)pConfig->beacon_int,
5715 (int)pConfig->channel);
5716 hddLog(LOGW,FL("hw_mode=%x, privacy=%d, authType=%d"),
5717 pConfig->SapHw_mode, pConfig->privacy,
5718 pConfig->authType);
5719 hddLog(LOGW,FL("RSN/WPALen=%d, Uapsd = %d"),
5720 (int)pConfig->RSNWPAReqIELength, pConfig->UapsdEnable);
5721 hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d"),
5722 pConfig->protEnabled, pConfig->obssProtEnabled);
Jeff Johnson295189b2012-06-20 16:38:30 -07005723
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305724 if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 {
5726 //Bss already started. just return.
5727 //TODO Probably it should update some beacon params.
5728 hddLog( LOGE, "Bss Already started...Ignore the request");
5729 EXIT();
5730 return 0;
5731 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305732
Agarwal Ashish51325b52014-06-16 16:50:49 +05305733 if (vos_max_concurrent_connections_reached()) {
5734 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
5735 return -EINVAL;
5736 }
5737
Jeff Johnson295189b2012-06-20 16:38:30 -07005738 pConfig->persona = pHostapdAdapter->device_mode;
5739
5740 pSapEventCallback = hdd_hostapd_SAPEventCB;
5741 if(WLANSAP_StartBss(pVosContext, pSapEventCallback, pConfig,
5742 (v_PVOID_t)pHostapdAdapter->dev) != VOS_STATUS_SUCCESS)
5743 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08005744 hddLog(LOGE,FL("SAP Start Bss fail"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005745 return -EINVAL;
5746 }
5747
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305748 hddLog(LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -07005749 FL("Waiting for Scan to complete(auto mode) and BSS to start"));
5750
5751 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305752
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 if (!VOS_IS_STATUS_SUCCESS(status))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305754 {
5755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005756 ("ERROR: HDD vos wait for single_event failed!!"));
Tushnim Bhattacharyyaad37df12013-10-02 12:01:33 -07005757 smeGetCommandQStatus(hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005758 VOS_ASSERT(0);
5759 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305760
Jeff Johnson295189b2012-06-20 16:38:30 -07005761 set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05305762 wlan_hdd_incr_active_session(pHddCtx, pHostapdAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005763
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07005764#ifdef WLAN_FEATURE_P2P_DEBUG
5765 if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
5766 {
5767 if(globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED)
5768 {
5769 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
5770 hddLog(LOGE,"[P2P State] From Go nego completed to "
Jeff Johnson1250df42012-12-10 14:31:52 -08005771 "Non-autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07005772 }
5773 else if(globalP2PConnectionStatus == P2P_NOT_ACTIVE)
5774 {
5775 globalP2PConnectionStatus = P2P_GO_COMPLETED_STATE;
5776 hddLog(LOGE,"[P2P State] From Inactive to "
Jeff Johnson1250df42012-12-10 14:31:52 -08005777 "Autonomous Group started");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07005778 }
5779 }
5780#endif
5781
Jeff Johnson295189b2012-06-20 16:38:30 -07005782 pHostapdState->bCommit = TRUE;
5783 EXIT();
5784
5785 return 0;
5786}
5787
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005788#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305789static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy,
5790 struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 struct beacon_parameters *params)
5792{
5793 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305794 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305795 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005796
5797 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305798
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305799 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
5800 TRACE_CODE_HDD_CFG80211_ADD_BEACON,
5801 pAdapter->sessionId, params->interval));
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05305802 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%s (%d)",
5803 hdd_device_modetoString(pAdapter->device_mode),
5804 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005805
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305806 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5807 status = wlan_hdd_validate_context(pHddCtx);
5808
5809 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005810 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5812 "%s: HDD context is not valid", __func__);
5813 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005814 }
5815
Agarwal Ashish51325b52014-06-16 16:50:49 +05305816 if (vos_max_concurrent_connections_reached()) {
5817 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
5818 return -EINVAL;
5819 }
5820
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305821 if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07005822 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 )
5824 {
5825 beacon_data_t *old,*new;
5826
5827 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305828
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305830 {
5831 hddLog(VOS_TRACE_LEVEL_WARN,
5832 FL("already beacon info added to session(%d)"),
5833 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005834 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305835 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005836
5837 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
5838
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305839 if(status != VOS_STATUS_SUCCESS)
Jeff Johnson295189b2012-06-20 16:38:30 -07005840 {
5841 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005842 "%s:Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005843 return -EINVAL;
5844 }
5845
5846 pAdapter->sessionCtx.ap.beacon = new;
5847
5848 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
5849 }
5850
5851 EXIT();
5852 return status;
5853}
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305854
5855static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07005856 struct net_device *dev,
5857 struct beacon_parameters *params)
5858{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305859 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305860 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5861 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305862 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -07005863
5864 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305865 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
5866 TRACE_CODE_HDD_CFG80211_SET_BEACON,
5867 pAdapter->sessionId, pHddStaCtx->conn_info.authType));
5868 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
5869 __func__, hdd_device_modetoString(pAdapter->device_mode),
5870 pAdapter->device_mode);
5871
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305872 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5873 status = wlan_hdd_validate_context(pHddCtx);
5874
5875 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005876 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5878 "%s: HDD context is not valid", __func__);
5879 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005880 }
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305881
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305882 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305884 )
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 {
5886 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305887
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305889
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305891 {
5892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5893 FL("session(%d) old and new heads points to NULL"),
5894 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005895 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305896 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005897
5898 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params);
5899
5900 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05305901 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005902 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005903 return -EINVAL;
5904 }
5905
5906 pAdapter->sessionCtx.ap.beacon = new;
5907
5908 status = wlan_hdd_cfg80211_start_bss(pAdapter, params);
5909 }
5910
5911 EXIT();
5912 return status;
5913}
5914
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005915#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
5916
5917#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07005918static int wlan_hdd_cfg80211_del_beacon(struct wiphy *wiphy,
5919 struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07005920#else
5921static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy,
5922 struct net_device *dev)
5923#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005924{
5925 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsone7245742012-09-05 17:12:55 -07005926 hdd_context_t *pHddCtx = NULL;
5927 hdd_scaninfo_t *pScanInfo = NULL;
5928 hdd_adapter_t *staAdapter = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305929 VOS_STATUS status;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305930 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005931
5932 ENTER();
5933
5934 if (NULL == pAdapter)
5935 {
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05305936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005937 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 return -ENODEV;
5939 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005940
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305941 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
5942 TRACE_CODE_HDD_CFG80211_STOP_AP,
5943 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305944 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5945 status = wlan_hdd_validate_context(pHddCtx);
5946
5947 if (0 != status)
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005948 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05305949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5950 "%s: HDD context is not valid", __func__);
5951 return status;
Jeff Johnson4416a782013-03-25 14:17:50 -07005952 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005953
5954 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION);
5955 if (NULL == staAdapter)
5956 {
5957 staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT);
5958 if (NULL == staAdapter)
5959 {
Rajesh Chauhan52d885b2013-11-01 10:54:25 -07005960 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
5961 "%s: HDD adapter context for STA/P2P-CLI is Null",
5962 __func__);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005963 }
5964 }
5965
5966 pScanInfo = &pHddCtx->scan_info;
5967
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05305968 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
5969 __func__, hdd_device_modetoString(pAdapter->device_mode),
5970 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005971
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305972 ret = wlan_hdd_scan_abort(pAdapter);
5973
Girish Gowli4bf7a632014-06-12 13:42:11 +05305974 if (ret < 0)
Jeff Johnsone7245742012-09-05 17:12:55 -07005975 {
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5977 FL("Timeout occurred while waiting for abortscan %ld"), ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305978
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305979 if (pHddCtx->isLogpInProgress)
Jeff Johnsone7245742012-09-05 17:12:55 -07005980 {
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305981 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5982 "%s: LOGP in Progress. Ignore!!!", __func__);
Yue Ma4f55ef32014-01-23 16:45:33 -08005983
Jeff Johnsone7245742012-09-05 17:12:55 -07005984 VOS_ASSERT(pScanInfo->mScanPending);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305985 return -EAGAIN;
Jeff Johnsone7245742012-09-05 17:12:55 -07005986 }
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05305987 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07005988 }
5989
Arun Kumar Khandavallia3bd8002014-01-17 16:21:19 +05305990 hdd_hostapd_stop(dev);
5991
Jeff Johnson295189b2012-06-20 16:38:30 -07005992 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07005993 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07005994 )
5995 {
5996 beacon_data_t *old;
5997
5998 old = pAdapter->sessionCtx.ap.beacon;
5999
6000 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306001 {
6002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6003 FL("session(%d) beacon data points to NULL"),
6004 pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306006 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006007
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006009
6010 mutex_lock(&pHddCtx->sap_lock);
6011 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6012 {
Jeff Johnson4416a782013-03-25 14:17:50 -07006013 if ( VOS_STATUS_SUCCESS == (status = WLANSAP_StopBss(pHddCtx->pvosContext) ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 {
6015 hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6016
6017 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6018
6019 if (!VOS_IS_STATUS_SUCCESS(status))
6020 {
6021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006022 ("ERROR: HDD vos wait for single_event failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07006023 VOS_ASSERT(0);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306024 }
6025 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05306027 /* BSS stopped, clear the active sessions for this device mode */
6028 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 }
6030 mutex_unlock(&pHddCtx->sap_lock);
6031
6032 if(status != VOS_STATUS_SUCCESS)
6033 {
6034 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006035 "%s:Error!!! Stopping the BSS",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006036 return -EINVAL;
6037 }
6038
Jeff Johnson4416a782013-03-25 14:17:50 -07006039 if (ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006040 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 0,NULL, eANI_BOOLEAN_FALSE)
6041 ==eHAL_STATUS_FAILURE)
6042 {
6043 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006044 "Could not pass on WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 }
6046
Jeff Johnson4416a782013-03-25 14:17:50 -07006047 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6049 eANI_BOOLEAN_FALSE) )
6050 {
6051 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006052 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 }
6054
6055 // Reset WNI_CFG_PROBE_RSP Flags
6056 wlan_hdd_reset_prob_rspies(pAdapter);
6057
6058 pAdapter->sessionCtx.ap.beacon = NULL;
6059 kfree(old);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07006060#ifdef WLAN_FEATURE_P2P_DEBUG
6061 if((pAdapter->device_mode == WLAN_HDD_P2P_GO) &&
6062 (globalP2PConnectionStatus == P2P_GO_COMPLETED_STATE))
6063 {
6064 hddLog(LOGE,"[P2P State] From GO completed to Inactive state "
6065 "GO got removed");
6066 globalP2PConnectionStatus = P2P_NOT_ACTIVE;
6067 }
6068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 }
6070 EXIT();
6071 return status;
6072}
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006073
6074#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
6075
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306076static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy,
6077 struct net_device *dev,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006078 struct cfg80211_ap_settings *params)
6079{
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306080 hdd_adapter_t *pAdapter;
6081 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306082 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006083
6084 ENTER();
6085
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306086 if (NULL == dev)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07006087 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306089 "%s: Device is Null", __func__);
6090 return -ENODEV;
6091 }
6092
6093 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6094 if (NULL == pAdapter)
6095 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306097 "%s: HDD adapter is Null", __func__);
6098 return -ENODEV;
6099 }
6100
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306101 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6102 TRACE_CODE_HDD_CFG80211_START_AP, pAdapter->sessionId,
6103 params-> beacon_interval));
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306104 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
6105 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306107 "%s: HDD adapter magic is invalid", __func__);
6108 return -ENODEV;
6109 }
6110
6111 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306112 status = wlan_hdd_validate_context(pHddCtx);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306113
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306114 if (0 != status)
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306115 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6117 "%s: HDD context is not valid", __func__);
6118 return status;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306119 }
6120
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05306121 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %s (%d)",
6122 __func__, hdd_device_modetoString(pAdapter->device_mode),
6123 pAdapter->device_mode);
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306124
6125 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006126 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006127 )
6128 {
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306129 beacon_data_t *old, *new;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006130
6131 old = pAdapter->sessionCtx.ap.beacon;
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306132
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006133 if (old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306134 {
6135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
6136 FL("already beacon info added to session(%d)"),
6137 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006138 return -EALREADY;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306139 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006140
6141 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, &params->beacon, params->dtim_period);
6142
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306143 if (status != 0)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006144 {
6145 hddLog(VOS_TRACE_LEVEL_FATAL,
Pratik Bhalgata0c7f262012-11-22 17:40:24 +05306146 "%s:Error!!! Allocating the new beacon", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006147 return -EINVAL;
6148 }
6149 pAdapter->sessionCtx.ap.beacon = new;
Viral Modi3a32cc52013-02-08 11:14:52 -08006150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Yue Maf49ba872013-08-19 12:04:25 -07006151 wlan_hdd_cfg80211_set_channel(wiphy, dev,
6152#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
6153 params->channel, params->channel_type);
6154#else
6155 params->chandef.chan, cfg80211_get_chandef_type(&(params->chandef)));
6156#endif
Viral Modi3a32cc52013-02-08 11:14:52 -08006157#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006158 status = wlan_hdd_cfg80211_start_bss(pAdapter, &params->beacon, params->ssid,
6159 params->ssid_len, params->hidden_ssid);
6160 }
6161
6162 EXIT();
6163 return status;
6164}
6165
6166
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306167static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006168 struct net_device *dev,
6169 struct cfg80211_beacon_data *params)
6170{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306171 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05306172 hdd_context_t *pHddCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306173 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006174
6175 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05306176
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306177 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6178 TRACE_CODE_HDD_CFG80211_CHANGE_BEACON,
6179 pAdapter->sessionId, pAdapter->device_mode));
Arif Hussain6d2a3322013-11-17 19:50:10 -08006180 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006181 __func__, pAdapter->device_mode);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306182
6183 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6184 status = wlan_hdd_validate_context(pHddCtx);
6185
6186 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07006187 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6189 "%s: HDD context is not valid", __func__);
6190 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07006191 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006192
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306193 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006194 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306195 )
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006196 {
6197 beacon_data_t *old,*new;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306198
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006199 old = pAdapter->sessionCtx.ap.beacon;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306200
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006201 if (!old)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306202 {
6203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6204 FL("session(%d) beacon data points to NULL"),
6205 pAdapter->sessionId);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006206 return -ENOENT;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306207 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006208
6209 status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0);
6210
6211 if(status != VOS_STATUS_SUCCESS) {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306212 hddLog(VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006213 "%s: Error!!! Allocating the new beacon",__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006214 return -EINVAL;
6215 }
6216
6217 pAdapter->sessionCtx.ap.beacon = new;
6218
6219 status = wlan_hdd_cfg80211_start_bss(pAdapter, params, NULL, 0, 0);
6220 }
6221
6222 EXIT();
6223 return status;
6224}
6225
6226#endif //(LINUX_VERSION_CODE > KERNEL_VERSION(3,3,0))
6227
Jeff Johnson295189b2012-06-20 16:38:30 -07006228
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +05306229static int __wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 struct net_device *dev,
6231 struct bss_parameters *params)
6232{
6233 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6234
6235 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05306236
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306237 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6238 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
6239 pAdapter->sessionId, params->ap_isolate));
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05306240 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
6241 __func__, hdd_device_modetoString(pAdapter->device_mode),
6242 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006243
6244 if((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07006245 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306246 )
Jeff Johnson295189b2012-06-20 16:38:30 -07006247 {
6248 /* ap_isolate == -1 means that in change bss, upper layer doesn't
6249 * want to update this parameter */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306250 if (-1 != params->ap_isolate)
Jeff Johnson295189b2012-06-20 16:38:30 -07006251 {
6252 pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306253 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006254 }
6255
6256 EXIT();
6257 return 0;
6258}
6259
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +05306260static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy,
6261 struct net_device *dev,
6262 struct bss_parameters *params)
6263{
6264 int ret;
6265
6266 vos_ssr_protect(__func__);
6267 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
6268 vos_ssr_unprotect(__func__);
6269
6270 return ret;
6271}
Kiet Lam10841362013-11-01 11:36:50 +05306272/* FUNCTION: wlan_hdd_change_country_code_cd
6273* to wait for contry code completion
6274*/
6275void* wlan_hdd_change_country_code_cb(void *pAdapter)
6276{
6277 hdd_adapter_t *call_back_pAdapter = pAdapter;
6278 complete(&call_back_pAdapter->change_country_code);
6279 return NULL;
6280}
6281
Jeff Johnson295189b2012-06-20 16:38:30 -07006282/*
Mahesh A Saptasagar0e59c472014-04-14 19:17:41 +05306283 * FUNCTION: __wlan_hdd_cfg80211_change_iface
Jeff Johnson295189b2012-06-20 16:38:30 -07006284 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
6285 */
Mahesh A Saptasagar0e59c472014-04-14 19:17:41 +05306286int __wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07006287 struct net_device *ndev,
6288 enum nl80211_iftype type,
6289 u32 *flags,
6290 struct vif_params *params
6291 )
6292{
6293 struct wireless_dev *wdev;
6294 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006295 hdd_context_t *pHddCtx;
Mohit Khanna0f232092012-09-11 14:46:08 -07006296 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006297 tCsrRoamProfile *pRoamProfile = NULL;
6298 eCsrRoamBssType LastBSSType;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306299 hdd_config_t *pConfig = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006300 eMib_dot11DesiredBssType connectedBssType;
6301 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306302 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006303
6304 ENTER();
6305
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306306 if (!pAdapter)
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006307 {
6308 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6309 "%s: Adapter context is null", __func__);
6310 return VOS_STATUS_E_FAILURE;
6311 }
6312
6313 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6314 if (!pHddCtx)
6315 {
6316 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6317 "%s: HDD context is null", __func__);
6318 return VOS_STATUS_E_FAILURE;
6319 }
6320
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306321 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6322 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
6323 pAdapter->sessionId, type));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306324 status = wlan_hdd_validate_context(pHddCtx);
6325
6326 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -07006327 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6329 "%s: HDD context is not valid", __func__);
6330 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 }
6332
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05306333 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
6334 __func__, hdd_device_modetoString(pAdapter->device_mode),
6335 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006336
Agarwal Ashish51325b52014-06-16 16:50:49 +05306337 if (vos_max_concurrent_connections_reached()) {
6338 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
6339 return -EINVAL;
6340 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05306341 pConfig = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 wdev = ndev->ieee80211_ptr;
6343
6344#ifdef WLAN_BTAMP_FEATURE
6345 if((NL80211_IFTYPE_P2P_CLIENT == type)||
6346 (NL80211_IFTYPE_ADHOC == type)||
6347 (NL80211_IFTYPE_AP == type)||
6348 (NL80211_IFTYPE_P2P_GO == type))
6349 {
6350 pHddCtx->isAmpAllowed = VOS_FALSE;
6351 // stop AMP traffic
6352 status = WLANBAP_StopAmp();
6353 if(VOS_STATUS_SUCCESS != status )
6354 {
6355 pHddCtx->isAmpAllowed = VOS_TRUE;
6356 hddLog(VOS_TRACE_LEVEL_FATAL,
6357 "%s: Failed to stop AMP", __func__);
6358 return -EINVAL;
6359 }
6360 }
6361#endif //WLAN_BTAMP_FEATURE
6362 /* Reset the current device mode bit mask*/
6363 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6364
6365 if( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnsone7245742012-09-05 17:12:55 -07006367 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
Jeff Johnson295189b2012-06-20 16:38:30 -07006368 )
6369 {
6370 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Rajesh Chauhana0516c62014-01-30 16:11:18 -08006371 if (!pWextState)
6372 {
6373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6374 "%s: pWextState is null", __func__);
6375 return VOS_STATUS_E_FAILURE;
6376 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006377 pRoamProfile = &pWextState->roamProfile;
6378 LastBSSType = pRoamProfile->BSSType;
6379
6380 switch (type)
6381 {
6382 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006383 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07006384 hddLog(VOS_TRACE_LEVEL_INFO,
6385 "%s: setting interface Type to INFRASTRUCTURE", __func__);
6386 pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE;
Jeff Johnsone7245742012-09-05 17:12:55 -07006387#ifdef WLAN_FEATURE_11AC
6388 if(pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO)
6389 {
6390 pConfig->dot11Mode = eHDD_DOT11_MODE_11ac;
6391 }
6392#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306393 pRoamProfile->phyMode =
Jeff Johnsone7245742012-09-05 17:12:55 -07006394 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006395 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08006396 //Check for sub-string p2p to confirm its a p2p interface
6397 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306398 {
Gopichand Nakkala864d3552012-12-31 16:08:51 -08006399 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
6400 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
6401 }
6402 else
6403 {
6404 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07006405 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08006406 }
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05306407#ifdef FEATURE_WLAN_TDLS
6408 /* The open adapter for the p2p shall skip initializations in
6409 * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for
6410 * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke
6411 * tdls_init when the change_iface sets the device mode to
6412 * WLAN_HDD_P2P_CLIENT.
6413 */
6414
6415 if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
6416 {
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306417 if (0 != wlan_hdd_sta_tdls_init (pAdapter))
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05306418 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306419 hddLog(VOS_TRACE_LEVEL_ERROR,
6420 "%s: tdls initialization failed", __func__);
Madan Mohan Koyyalamudi81746922013-07-17 14:38:51 +05306421 return -EINVAL;
6422 }
6423 }
6424#endif
6425
Jeff Johnson295189b2012-06-20 16:38:30 -07006426 break;
6427 case NL80211_IFTYPE_ADHOC:
6428 hddLog(VOS_TRACE_LEVEL_INFO,
6429 "%s: setting interface Type to ADHOC", __func__);
6430 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
6431 pRoamProfile->phyMode =
6432 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
Shailender Karmuchia734f332013-04-19 14:02:48 -07006433 pAdapter->device_mode = WLAN_HDD_IBSS;
Jeff Johnson295189b2012-06-20 16:38:30 -07006434 wdev->iftype = type;
6435 break;
6436
6437 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006438 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006439 {
6440 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
6441 "%s: setting interface Type to %s", __func__,
6442 (type == NL80211_IFTYPE_AP) ? "SoftAP" : "P2pGo");
6443
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08006444 //Cancel any remain on channel for GO mode
6445 if (NL80211_IFTYPE_P2P_GO == type)
6446 {
6447 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
6448 }
Mohit Khanna0f232092012-09-11 14:46:08 -07006449 if (NL80211_IFTYPE_AP == type)
6450 {
6451 /* As Loading WLAN Driver one interface being created for p2p device
6452 * address. This will take one HW STA and the max number of clients
6453 * that can connect to softAP will be reduced by one. so while changing
6454 * the interface type to NL80211_IFTYPE_AP (SoftAP) remove p2p0
6455 * interface as it is not required in SoftAP mode.
6456 */
6457
6458 // Get P2P Adapter
6459 pP2pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE);
6460
6461 if (pP2pAdapter)
6462 {
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306463 hdd_stop_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
Mohit Khanna0f232092012-09-11 14:46:08 -07006464 hdd_deinit_adapter(pHddCtx, pP2pAdapter);
6465 hdd_close_adapter(pHddCtx, pP2pAdapter, VOS_TRUE);
6466 }
6467 }
Swaroop Goltia2e32212014-04-09 23:37:33 +05306468 //Disable IMPS & BMPS for SAP/GO
6469 if(VOS_STATUS_E_FAILURE ==
6470 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO))
6471 {
6472 //Fail to Exit BMPS
6473 VOS_ASSERT(0);
6474 }
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306475#ifdef FEATURE_WLAN_TDLS
Mohit Khanna0f232092012-09-11 14:46:08 -07006476
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306477 /* A Mutex Lock is introduced while changing the mode to
6478 * protect the concurrent access for the Adapters by TDLS
6479 * module.
6480 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306481 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306482#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006483 //De-init the adapter.
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306484 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 hdd_deinit_adapter( pHddCtx, pAdapter );
6486 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
Jeff Johnson295189b2012-06-20 16:38:30 -07006487 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
6488 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306489#ifdef FEATURE_WLAN_TDLS
6490 mutex_unlock(&pHddCtx->tdls_lock);
6491#endif
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07006492 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) &&
6493 (pConfig->apRandomBssidEnabled))
6494 {
6495 /* To meet Android requirements create a randomized
6496 MAC address of the form 02:1A:11:Fx:xx:xx */
6497 get_random_bytes(&ndev->dev_addr[3], 3);
6498 ndev->dev_addr[0] = 0x02;
6499 ndev->dev_addr[1] = 0x1A;
6500 ndev->dev_addr[2] = 0x11;
6501 ndev->dev_addr[3] |= 0xF0;
6502 memcpy(pAdapter->macAddressCurrent.bytes, ndev->dev_addr,
6503 VOS_MAC_ADDR_SIZE);
Arif Hussain24bafea2013-11-15 15:10:03 -08006504 pr_info("wlan: Generated HotSpot BSSID " MAC_ADDRESS_STR"\n",
6505 MAC_ADDR_ARRAY(ndev->dev_addr));
Madan Mohan Koyyalamudi3ff2a0b2012-10-15 14:33:46 -07006506 }
6507
Jeff Johnson295189b2012-06-20 16:38:30 -07006508 hdd_set_ap_ops( pAdapter->dev );
6509
Kiet Lam10841362013-11-01 11:36:50 +05306510 /* This is for only SAP mode where users can
6511 * control country through ini.
6512 * P2P GO follows station country code
6513 * acquired during the STA scanning. */
6514 if((NL80211_IFTYPE_AP == type) &&
6515 (memcmp(pConfig->apCntryCode, CFG_AP_COUNTRY_CODE_DEFAULT, 3) != 0))
6516 {
6517 int status = 0;
6518 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_INFO,
6519 "%s: setting country code from INI ", __func__);
6520 init_completion(&pAdapter->change_country_code);
6521 status = (int)sme_ChangeCountryCode(pHddCtx->hHal,
6522 (void *)(tSmeChangeCountryCallback)
6523 wlan_hdd_change_country_code_cb,
6524 pConfig->apCntryCode, pAdapter,
6525 pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05306526 eSIR_FALSE,
6527 eSIR_TRUE);
Kiet Lam10841362013-11-01 11:36:50 +05306528 if (eHAL_STATUS_SUCCESS == status)
6529 {
6530 /* Wait for completion */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306531 ret = wait_for_completion_interruptible_timeout(
Kiet Lam10841362013-11-01 11:36:50 +05306532 &pAdapter->change_country_code,
6533 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306534 if (ret <= 0)
Kiet Lam10841362013-11-01 11:36:50 +05306535 {
6536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306537 FL("SME Timed out while setting country code %ld"),
6538 ret);
Yue Ma4f55ef32014-01-23 16:45:33 -08006539
6540 if (pHddCtx->isLogpInProgress)
6541 {
6542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6543 "%s: LOGP in Progress. Ignore!!!", __func__);
6544 return -EAGAIN;
6545 }
Kiet Lam10841362013-11-01 11:36:50 +05306546 }
6547 }
6548 else
6549 {
6550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006551 "%s: SME Change Country code failed",__func__);
Kiet Lam10841362013-11-01 11:36:50 +05306552 return -EINVAL;
6553 }
6554 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006555 status = hdd_init_ap_mode(pAdapter);
6556 if(status != VOS_STATUS_SUCCESS)
6557 {
6558 hddLog(VOS_TRACE_LEVEL_FATAL,
6559 "%s: Error initializing the ap mode", __func__);
6560 return -EINVAL;
6561 }
6562 hdd_set_conparam(1);
6563
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 /*interface type changed update in wiphy structure*/
6565 if(wdev)
6566 {
6567 wdev->iftype = type;
6568 pHddCtx->change_iface = type;
6569 }
6570 else
6571 {
6572 hddLog(VOS_TRACE_LEVEL_ERROR,
6573 "%s: ERROR !!!! Wireless dev is NULL", __func__);
6574 return -EINVAL;
6575 }
6576 goto done;
6577 }
6578
6579 default:
6580 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
6581 __func__);
6582 return -EOPNOTSUPP;
6583 }
6584 }
6585 else if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07006586 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Jeff Johnson295189b2012-06-20 16:38:30 -07006587 )
6588 {
6589 switch(type)
6590 {
6591 case NL80211_IFTYPE_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006592 case NL80211_IFTYPE_P2P_CLIENT:
Jeff Johnson295189b2012-06-20 16:38:30 -07006593 case NL80211_IFTYPE_ADHOC:
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306594#ifdef FEATURE_WLAN_TDLS
6595
6596 /* A Mutex Lock is introduced while changing the mode to
6597 * protect the concurrent access for the Adapters by TDLS
6598 * module.
6599 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306600 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306601#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306602 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson32d95a32012-09-10 13:15:23 -07006603 hdd_deinit_adapter( pHddCtx, pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006604 wdev->iftype = type;
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -08006605 //Check for sub-string p2p to confirm its a p2p interface
6606 if (NULL != strstr(ndev->name,"p2p"))
Gopichand Nakkala864d3552012-12-31 16:08:51 -08006607 {
6608 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
6609 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
6610 }
6611 else
6612 {
6613 pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ?
Jeff Johnson295189b2012-06-20 16:38:30 -07006614 WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT;
Gopichand Nakkala864d3552012-12-31 16:08:51 -08006615 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006616 hdd_set_conparam(0);
6617 pHddCtx->change_iface = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07006618 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
6619 hdd_set_station_ops( pAdapter->dev );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306620#ifdef FEATURE_WLAN_TDLS
6621 mutex_unlock(&pHddCtx->tdls_lock);
6622#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306623 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006624 if( VOS_STATUS_SUCCESS != status )
6625 return -EOPNOTSUPP;
Jeff Johnsone7245742012-09-05 17:12:55 -07006626 /* In case of JB, for P2P-GO, only change interface will be called,
6627 * This is the right place to enable back bmps_imps()
6628 */
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306629 if (pHddCtx->hdd_wlan_suspended)
6630 {
6631 hdd_set_pwrparams(pHddCtx);
6632 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006633 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006634 goto done;
6635 case NL80211_IFTYPE_AP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006636 case NL80211_IFTYPE_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006637 wdev->iftype = type;
Jeff Johnson295189b2012-06-20 16:38:30 -07006638 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
6639 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006640 goto done;
6641 default:
6642 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported interface Type",
6643 __func__);
6644 return -EOPNOTSUPP;
6645
6646 }
6647
6648 }
6649 else
6650 {
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05306651 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: unsupported device mode(%s (%d))",
6652 __func__, hdd_device_modetoString(pAdapter->device_mode),
6653 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006654 return -EOPNOTSUPP;
6655 }
6656
6657
6658 if(pRoamProfile)
6659 {
6660 if ( LastBSSType != pRoamProfile->BSSType )
6661 {
6662 /*interface type changed update in wiphy structure*/
6663 wdev->iftype = type;
6664
6665 /*the BSS mode changed, We need to issue disconnect
6666 if connected or in IBSS disconnect state*/
6667 if ( hdd_connGetConnectedBssType(
6668 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) ||
6669 ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) )
6670 {
6671 /*need to issue a disconnect to CSR.*/
6672 INIT_COMPLETION(pAdapter->disconnect_comp_var);
6673 if( eHAL_STATUS_SUCCESS ==
6674 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
6675 pAdapter->sessionId,
6676 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
6677 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306678 ret = wait_for_completion_interruptible_timeout(
6679 &pAdapter->disconnect_comp_var,
6680 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6681 if (ret <= 0)
6682 {
6683 hddLog(VOS_TRACE_LEVEL_ERROR,
6684 FL("wait on disconnect_comp_var failed %ld"), ret);
6685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006686 }
6687 }
6688 }
6689 }
6690
6691done:
6692 /*set bitmask based on updated value*/
6693 wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
Leo Chang6fe1f922013-06-07 19:21:24 -07006694
6695 /* Only STA mode support TM now
6696 * all other mode, TM feature should be disabled */
6697 if ( (pHddCtx->cfg_ini->thermalMitigationEnable) &&
6698 (~VOS_STA & pHddCtx->concurrency_mode) )
6699 {
6700 hddDevTmLevelChangedHandler(pHddCtx->parent_dev, 0);
6701 }
6702
Jeff Johnson295189b2012-06-20 16:38:30 -07006703#ifdef WLAN_BTAMP_FEATURE
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306704 if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) &&
Agarwal Ashish51325b52014-06-16 16:50:49 +05306705 (pHddCtx->no_of_open_sessions[WLAN_HDD_INFRA_STATION] <=1))
Jeff Johnson295189b2012-06-20 16:38:30 -07006706 {
6707 //we are ok to do AMP
6708 pHddCtx->isAmpAllowed = VOS_TRUE;
6709 }
6710#endif //WLAN_BTAMP_FEATURE
6711 EXIT();
6712 return 0;
6713}
6714
Mahesh A Saptasagar0e59c472014-04-14 19:17:41 +05306715/*
6716 * FUNCTION: wlan_hdd_cfg80211_change_iface
6717 * wrapper function to protect the actual implementation from SSR.
6718 */
6719int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy,
6720 struct net_device *ndev,
6721 enum nl80211_iftype type,
6722 u32 *flags,
6723 struct vif_params *params
6724 )
6725{
6726 int ret;
6727
6728 vos_ssr_protect(__func__);
6729 ret = __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
6730 vos_ssr_unprotect(__func__);
6731
6732 return ret;
6733}
6734
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006735#ifdef FEATURE_WLAN_TDLS
6736static int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
6737 struct net_device *dev, u8 *mac, bool update, tCsrStaParams *StaParams)
6738{
6739 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6740 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6741 VOS_STATUS status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07006742 hddTdlsPeer_t *pTdlsPeer;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306743 long ret;
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306744 tANI_U16 numCurrTdlsPeers;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006745
6746 ENTER();
6747
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05306748 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006749 {
6750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6751 "Invalid arguments");
6752 return -EINVAL;
6753 }
Hoonki Lee27511902013-03-14 18:19:06 -07006754
6755 if ((eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) ||
6756 (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode))
6757 {
6758 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6759 "%s: TDLS mode is disabled OR not enabled in FW."
6760 MAC_ADDRESS_STR " Request declined.",
6761 __func__, MAC_ADDR_ARRAY(mac));
6762 return -ENOTSUPP;
6763 }
6764
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006765 if (pHddCtx->isLogpInProgress)
6766 {
6767 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6768 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006769 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006770 return -EBUSY;
6771 }
6772
Naresh Jayaram9c6f4462014-02-13 12:20:31 +05306773 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07006774
6775 if ( NULL == pTdlsPeer ) {
6776 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6777 "%s: " MAC_ADDRESS_STR " (update %d) not exist. return invalid",
6778 __func__, MAC_ADDR_ARRAY(mac), update);
6779 return -EINVAL;
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006780 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -07006781
6782 /* in add station, we accept existing valid staId if there is */
6783 if ((0 == update) &&
6784 ((pTdlsPeer->link_status >= eTDLS_LINK_CONNECTING) ||
6785 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006786 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -07006787 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006788 "%s: " MAC_ADDRESS_STR
Hoonki Lee5305c3a2013-04-29 23:28:59 -07006789 " link_status %d. staId %d. add station ignored.",
6790 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId);
6791 return 0;
6792 }
6793 /* in change station, we accept only when staId is valid */
6794 if ((1 == update) &&
6795 ((pTdlsPeer->link_status > eTDLS_LINK_CONNECTING) ||
6796 (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))))
6797 {
6798 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6799 "%s: " MAC_ADDRESS_STR
6800 " link status %d. staId %d. change station %s.",
6801 __func__, MAC_ADDR_ARRAY(mac), pTdlsPeer->link_status, pTdlsPeer->staId,
6802 (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? "ignored" : "declined");
6803 return (TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) ? 0 : -EPERM;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006804 }
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006805
6806 /* when others are on-going, we want to change link_status to idle */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306807 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006808 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6810 "%s: " MAC_ADDRESS_STR
6811 " TDLS setup is ongoing. Request declined.",
6812 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala05922802013-03-14 12:23:19 -07006813 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006814 }
6815
6816 /* first to check if we reached to maximum supported TDLS peer.
6817 TODO: for now, return -EPERM looks working fine,
6818 but need to check if any other errno fit into this category.*/
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306819 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
6820 if (HDD_MAX_NUM_TDLS_STA <= numCurrTdlsPeers)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006821 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6823 "%s: " MAC_ADDRESS_STR
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306824 " TDLS Max peer already connected. Request declined."
6825 " Num of peers (%d), Max allowed (%d).",
6826 __func__, MAC_ADDR_ARRAY(mac), numCurrTdlsPeers,
6827 HDD_MAX_NUM_TDLS_STA);
Gopichand Nakkala05922802013-03-14 12:23:19 -07006828 goto error;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006829 }
6830 else
6831 {
6832 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306833 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, mac, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006834 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006835 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6837 "%s: " MAC_ADDRESS_STR " already connected. Request declined.",
6838 __func__, MAC_ADDR_ARRAY(mac));
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006839 return -EPERM;
6840 }
6841 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006842 if (0 == update)
6843 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING);
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006844
Jeff Johnsond75fe012013-04-06 10:53:06 -07006845 /* debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05306846 if (NULL != StaParams)
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006847 {
6848 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6849 "%s: TDLS Peer Parameters.", __func__);
Hoonki Lee66b75f32013-04-16 18:30:07 -07006850 if(StaParams->htcap_present)
6851 {
6852 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6853 "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo);
6854 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6855 "ht_capa->extended_capabilities: %0x",
6856 StaParams->HTCap.extendedHtCapInfo);
6857 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006858 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6859 "params->capability: %0x",StaParams->capability);
6860 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006861 "params->ext_capab_len: %0x",StaParams->extn_capability[0]);
Hoonki Lee66b75f32013-04-16 18:30:07 -07006862 if(StaParams->vhtcap_present)
6863 {
6864 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6865 "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x",
6866 StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest,
6867 StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest);
6868 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006869 {
6870 int i = 0;
Hoonki Lee5305c3a2013-04-29 23:28:59 -07006871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Supported rates:");
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006872 for (i = 0; i < sizeof(StaParams->supported_rates); i++)
6873 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
6874 "[%d]: %x ", i, StaParams->supported_rates[i]);
6875 }
Jeff Johnsond75fe012013-04-06 10:53:06 -07006876 } /* end debug code */
Gopichand Nakkala838be5d2013-04-10 22:41:51 +05306877 else if ((1 == update) && (NULL == StaParams))
6878 {
6879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6880 "%s : update is true, but staParams is NULL. Error!", __func__);
6881 return -EPERM;
6882 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006883
6884 INIT_COMPLETION(pAdapter->tdls_add_station_comp);
6885
6886 if (!update)
6887 {
6888 status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6889 pAdapter->sessionId, mac);
6890 }
6891 else
6892 {
6893 status = sme_ChangeTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
6894 pAdapter->sessionId, mac, StaParams);
6895 }
6896
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306897 ret = wait_for_completion_interruptible_timeout(&pAdapter->tdls_add_station_comp,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006898 msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
6899
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306900 if (ret <= 0)
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006901 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006902 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306903 "%s: timeout waiting for tdls add station indication %ld",
6904 __func__, ret);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006905 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006906 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306907
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006908 if ( eHAL_STATUS_SUCCESS != pAdapter->tdlsAddStaStatus)
6909 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -07006910 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006911 "%s: Add Station is unsucessful", __func__);
Gopichand Nakkala34d1b062013-03-19 15:28:33 -07006912 return -EPERM;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006913 }
6914
6915 return 0;
Gopichand Nakkala05922802013-03-14 12:23:19 -07006916
6917error:
6918 wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_IDLE);
6919 return -EPERM;
6920
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006921}
6922#endif
6923
Jeff Johnson295189b2012-06-20 16:38:30 -07006924static int wlan_hdd_change_station(struct wiphy *wiphy,
6925 struct net_device *dev,
6926 u8 *mac,
6927 struct station_parameters *params)
6928{
6929 VOS_STATUS status = VOS_STATUS_SUCCESS;
6930 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkala29149562013-05-10 21:43:41 +05306931 hdd_context_t *pHddCtx;
6932 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006933 v_MACADDR_t STAMacAddress;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07006934#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006935 tCsrStaParams StaParams = {0};
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006936 tANI_U8 isBufSta = 0;
Naresh Jayaram3180aa42014-02-12 21:47:26 +05306937 tANI_U8 isOffChannelSupported = 0;
Gopichand Nakkalab0856222013-03-12 22:39:05 -07006938#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07006939 ENTER();
6940
Gopichand Nakkala29149562013-05-10 21:43:41 +05306941 if ((NULL == pAdapter))
6942 {
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05306943 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Gopichand Nakkala29149562013-05-10 21:43:41 +05306944 "invalid adapter ");
6945 return -EINVAL;
6946 }
6947
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306948 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6949 TRACE_CODE_HDD_CHANGE_STATION,
6950 pAdapter->sessionId, params->listen_interval));
Gopichand Nakkala29149562013-05-10 21:43:41 +05306951 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6952 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6953
6954 if ((NULL == pHddCtx) || (NULL == pHddStaCtx))
6955 {
6956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6957 "invalid HDD state or HDD station context");
6958 return -EINVAL;
6959 }
6960
6961 if (pHddCtx->isLogpInProgress)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07006962 {
6963 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6964 "%s:LOGP in Progress. Ignore!!!", __func__);
6965 return -EAGAIN;
6966 }
6967
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 vos_mem_copy(STAMacAddress.bytes, mac, sizeof(v_MACADDR_t));
6969
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006970 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
6971 || (pAdapter->device_mode == WLAN_HDD_P2P_GO))
Jeff Johnson295189b2012-06-20 16:38:30 -07006972 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08006973 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
Jeff Johnson295189b2012-06-20 16:38:30 -07006974 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05306975 status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress,
Jeff Johnson295189b2012-06-20 16:38:30 -07006976 WLANTL_STA_AUTHENTICATED);
6977
Gopichand Nakkala29149562013-05-10 21:43:41 +05306978 if (status != VOS_STATUS_SUCCESS)
6979 {
6980 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6981 "%s: Not able to change TL state to AUTHENTICATED", __func__);
6982 return -EINVAL;
6983 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 }
6985 }
Hoonki Leea6d49be2013-04-05 09:43:25 -07006986 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6987 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
Gopichand Nakkala29149562013-05-10 21:43:41 +05306988#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006989 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6990 StaParams.capability = params->capability;
6991 StaParams.uapsd_queues = params->uapsd_queues;
6992 StaParams.max_sp = params->max_sp;
6993
Naresh Jayaram3180aa42014-02-12 21:47:26 +05306994 /* Convert (first channel , number of channels) tuple to
6995 * the total list of channels. This goes with the assumption
6996 * that if the first channel is < 14, then the next channels
6997 * are an incremental of 1 else an incremental of 4 till the number
6998 * of channels.
6999 */
7000 if (0 != params->supported_channels_len) {
7001 int i = 0,j = 0,k = 0, no_of_channels = 0 ;
7002 for ( i = 0 ; i < params->supported_channels_len ; i+=2)
7003 {
7004 int wifi_chan_index;
7005 StaParams.supported_channels[j] = params->supported_channels[i];
7006 wifi_chan_index =
7007 ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 );
7008 no_of_channels = params->supported_channels[i+1];
7009 for(k=1; k <= no_of_channels; k++)
7010 {
7011 StaParams.supported_channels[j+1] =
7012 StaParams.supported_channels[j] + wifi_chan_index;
7013 j+=1;
7014 }
7015 }
7016 StaParams.supported_channels_len = j;
7017 }
7018 vos_mem_copy(StaParams.supported_oper_classes,
7019 params->supported_oper_classes,
7020 params->supported_oper_classes_len);
7021 StaParams.supported_oper_classes_len =
7022 params->supported_oper_classes_len;
7023
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007024 if (0 != params->ext_capab_len)
7025 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
7026 sizeof(StaParams.extn_capability));
7027
7028 if (NULL != params->ht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07007029 {
7030 StaParams.htcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007031 vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07007032 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007033
7034 StaParams.supported_rates_len = params->supported_rates_len;
7035
7036 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
7037 * The supported_rates array , for all the structures propogating till Add Sta
7038 * to the firmware has to be modified , if the supplicant (ieee80211) is
7039 * modified to send more rates.
7040 */
7041
7042 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
7043 */
7044 if (StaParams.supported_rates_len > SIR_MAC_MAX_SUPP_RATES)
7045 StaParams.supported_rates_len = SIR_MAC_MAX_SUPP_RATES;
7046
7047 if (0 != StaParams.supported_rates_len) {
7048 int i = 0;
7049 vos_mem_copy(StaParams.supported_rates, params->supported_rates,
7050 StaParams.supported_rates_len);
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007052 "Supported Rates with Length %d", StaParams.supported_rates_len);
7053 for (i=0; i < StaParams.supported_rates_len; i++)
Hoonki Lee5305c3a2013-04-29 23:28:59 -07007054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007055 "[%d]: %0x", i, StaParams.supported_rates[i]);
7056 }
7057
7058 if (NULL != params->vht_capa)
Hoonki Lee66b75f32013-04-16 18:30:07 -07007059 {
7060 StaParams.vhtcap_present = 1;
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007061 vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap));
Hoonki Lee66b75f32013-04-16 18:30:07 -07007062 }
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07007063
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007064 if (0 != params->ext_capab_len ) {
7065 /*Define A Macro : TODO Sunil*/
7066 if ((1<<4) & StaParams.extn_capability[3]) {
7067 isBufSta = 1;
7068 }
Naresh Jayaram3180aa42014-02-12 21:47:26 +05307069 /* TDLS Channel Switching Support */
7070 if ((1<<6) & StaParams.extn_capability[3]) {
7071 isOffChannelSupported = 1;
7072 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007073 }
Naresh Jayaram3180aa42014-02-12 21:47:26 +05307074 status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac,
7075 &StaParams, isBufSta,
7076 isOffChannelSupported);
7077
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05307078 if (VOS_STATUS_SUCCESS != status) {
7079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7080 "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
7081 return -EINVAL;
7082 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08007083 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 1, &StaParams);
7084
7085 if (VOS_STATUS_SUCCESS != status) {
7086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7087 "%s: sme_ChangeTdlsPeerSta failed!", __func__);
7088 return -EINVAL;
7089 }
7090 }
Gopichand Nakkalab0856222013-03-12 22:39:05 -07007091#endif
Gopichand Nakkala6239acd2013-06-14 14:48:00 +05307092 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007093 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007094 return status;
7095}
7096
7097/*
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307098 * FUNCTION: __wlan_hdd_cfg80211_add_key
Jeff Johnson295189b2012-06-20 16:38:30 -07007099 * This function is used to initialize the key information
7100 */
7101#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307102static int __wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007103 struct net_device *ndev,
7104 u8 key_index, bool pairwise,
7105 const u8 *mac_addr,
7106 struct key_params *params
7107 )
7108#else
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307109static int __wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007110 struct net_device *ndev,
7111 u8 key_index, const u8 *mac_addr,
7112 struct key_params *params
7113 )
7114#endif
7115{
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007116 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Jeff Johnson295189b2012-06-20 16:38:30 -07007117 tCsrRoamSetKey setKey;
7118 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307119 int status;
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007120 v_U32_t roamId= 0xFF;
7121 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007122 hdd_hostapd_state_t *pHostapdState;
7123 VOS_STATUS vos_status;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007124 eHalStatus halStatus;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307125 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007126
7127 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05307128
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307129 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7130 TRACE_CODE_HDD_CFG80211_ADD_KEY,
7131 pAdapter->sessionId, params->key_len));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307132 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7133 status = wlan_hdd_validate_context(pHddCtx);
7134
7135 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007136 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307137 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7138 "%s: HDD context is not valid", __func__);
7139 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007140 }
7141
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05307142 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
7143 __func__, hdd_device_modetoString(pAdapter->device_mode),
7144 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07007145
7146 if (CSR_MAX_NUM_KEY <= key_index)
7147 {
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007148 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007149 key_index);
7150
7151 return -EINVAL;
7152 }
7153
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007154 if (CSR_MAX_KEY_LEN < params->key_len)
7155 {
7156 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key length %d", __func__,
7157 params->key_len);
7158
7159 return -EINVAL;
7160 }
7161
7162 hddLog(VOS_TRACE_LEVEL_INFO,
7163 "%s: called with key index = %d & key length %d",
7164 __func__, key_index, params->key_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07007165
7166 /*extract key idx, key len and key*/
7167 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
7168 setKey.keyId = key_index;
7169 setKey.keyLength = params->key_len;
7170 vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
7171
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007172 switch (params->cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07007173 {
7174 case WLAN_CIPHER_SUITE_WEP40:
7175 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
7176 break;
7177
7178 case WLAN_CIPHER_SUITE_WEP104:
7179 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
7180 break;
7181
7182 case WLAN_CIPHER_SUITE_TKIP:
7183 {
7184 u8 *pKey = &setKey.Key[0];
7185 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
7186
7187 vos_mem_zero(pKey, CSR_MAX_KEY_LEN);
7188
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007189 /*Supplicant sends the 32bytes key in this order
Jeff Johnson295189b2012-06-20 16:38:30 -07007190
7191 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007192 | Tk1 |TX-MIC | RX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07007193 |--------------|----------|----------|
7194 <---16bytes---><--8bytes--><--8bytes-->
7195
7196 */
7197 /*Sme expects the 32 bytes key to be in the below order
7198
7199 |--------------|----------|----------|
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007200 | Tk1 |RX-MIC | TX Mic |
Jeff Johnson295189b2012-06-20 16:38:30 -07007201 |--------------|----------|----------|
7202 <---16bytes---><--8bytes--><--8bytes-->
7203 */
7204 /* Copy the Temporal Key 1 (TK1) */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007205 vos_mem_copy(pKey, params->key, 16);
Jeff Johnson295189b2012-06-20 16:38:30 -07007206
7207 /*Copy the rx mic first*/
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007208 vos_mem_copy(&pKey[16], &params->key[24], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07007209
7210 /*Copy the tx mic */
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007211 vos_mem_copy(&pKey[24], &params->key[16], 8);
Jeff Johnson295189b2012-06-20 16:38:30 -07007212
7213
7214 break;
7215 }
7216
7217 case WLAN_CIPHER_SUITE_CCMP:
7218 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
7219 break;
7220
7221#ifdef FEATURE_WLAN_WAPI
7222 case WLAN_CIPHER_SUITE_SMS4:
7223 {
7224 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
7225 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index, mac_addr,
7226 params->key, params->key_len);
7227 return 0;
7228 }
7229#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07007230
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007231#ifdef FEATURE_WLAN_ESE
Jeff Johnson295189b2012-06-20 16:38:30 -07007232 case WLAN_CIPHER_SUITE_KRK:
7233 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
7234 break;
7235#endif
Chet Lanctot186b5732013-03-18 10:26:30 -07007236
7237#ifdef WLAN_FEATURE_11W
7238 case WLAN_CIPHER_SUITE_AES_CMAC:
7239 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
Chet Lanctot3b5158a2013-03-31 16:45:21 -07007240 break;
Chet Lanctot186b5732013-03-18 10:26:30 -07007241#endif
7242
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 default:
Jeff Johnson0299d0a2013-10-30 12:37:43 -07007244 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07007245 __func__, params->cipher);
7246 return -EOPNOTSUPP;
7247 }
7248
7249 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
7250 __func__, setKey.encType);
7251
Shailender Karmuchi642e9812013-05-30 14:34:49 -07007252 if (
Jeff Johnson295189b2012-06-20 16:38:30 -07007253#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7254 (!pairwise)
7255#else
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007256 (!mac_addr || is_broadcast_ether_addr(mac_addr))
Jeff Johnson295189b2012-06-20 16:38:30 -07007257#endif
Shailender Karmuchi642e9812013-05-30 14:34:49 -07007258 )
7259 {
7260 /* set group key*/
7261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7262 "%s- %d: setting Broadcast key",
7263 __func__, __LINE__);
7264 setKey.keyDirection = eSIR_RX_ONLY;
7265 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
7266 }
7267 else
7268 {
7269 /* set pairwise key*/
7270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7271 "%s- %d: setting pairwise key",
7272 __func__, __LINE__);
7273 setKey.keyDirection = eSIR_TX_RX;
7274 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
7275 }
7276 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
7277 {
7278 setKey.keyDirection = eSIR_TX_RX;
7279 /*Set the group key*/
7280 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
7281 pAdapter->sessionId, &setKey, &roamId );
Jeff Johnson295189b2012-06-20 16:38:30 -07007282
Shailender Karmuchi642e9812013-05-30 14:34:49 -07007283 if ( 0 != status )
7284 {
7285 hddLog(VOS_TRACE_LEVEL_ERROR,
7286 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
7287 return -EINVAL;
7288 }
7289 /*Save the keys here and call sme_RoamSetKey for setting
7290 the PTK after peer joins the IBSS network*/
7291 vos_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
7292 &setKey, sizeof(tCsrRoamSetKey));
7293 return status;
7294 }
Gopichand Nakkala29149562013-05-10 21:43:41 +05307295 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
7296 (pAdapter->device_mode == WLAN_HDD_P2P_GO))
7297 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007298 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007299 if( pHostapdState->bssState == BSS_START )
7300 {
c_hpothu7c55da62014-01-23 18:34:02 +05307301 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7302 vos_status = wlan_hdd_check_ula_done(pAdapter);
7303
7304 if ( vos_status != VOS_STATUS_SUCCESS )
7305 {
7306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7307 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
7308 __LINE__, vos_status );
7309
7310 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
7311
7312 return -EINVAL;
7313 }
7314
Jeff Johnson295189b2012-06-20 16:38:30 -07007315 status = WLANSAP_SetKeySta( pVosContext, &setKey);
7316
7317 if ( status != eHAL_STATUS_SUCCESS )
7318 {
7319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7320 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
7321 __LINE__, status );
7322 }
7323 }
7324
7325 /* Saving WEP keys */
7326 else if( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
7327 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType )
7328 {
7329 //Save the wep key in ap context. Issue setkey after the BSS is started.
7330 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7331 vos_mem_copy(&pAPCtx->wepKey[key_index], &setKey, sizeof(tCsrRoamSetKey));
7332 }
7333 else
7334 {
7335 //Save the key in ap context. Issue setkey after the BSS is started.
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007336 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007337 vos_mem_copy(&pAPCtx->groupKey, &setKey, sizeof(tCsrRoamSetKey));
7338 }
7339 }
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007340 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
7341 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007342 {
7343 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7344 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7345
Gopichand Nakkala3d295922013-05-07 16:19:14 +05307346#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7347 if (!pairwise)
7348#else
7349 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
7350#endif
7351 {
7352 /* set group key*/
7353 if (pHddStaCtx->roam_info.deferKeyComplete)
7354 {
7355 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7356 "%s- %d: Perform Set key Complete",
7357 __func__, __LINE__);
7358 hdd_PerformRoamSetKeyComplete(pAdapter);
7359 }
7360 }
7361
Jeff Johnson295189b2012-06-20 16:38:30 -07007362 pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
7363
Venkata Prathyusha Kuntupalliee2ce712013-01-17 14:09:24 -08007364 pWextState->roamProfile.Keys.defaultIndex = key_index;
7365
7366
Jeff Johnsonf77ef0a2013-03-27 09:29:14 -07007367 vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07007368 params->key, params->key_len);
7369
Gopichand Nakkala3d295922013-05-07 16:19:14 +05307370
Jeff Johnson295189b2012-06-20 16:38:30 -07007371 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
7372
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307373 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07007374 "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307375 __func__, setKey.peerMac[0], setKey.peerMac[1],
7376 setKey.peerMac[2], setKey.peerMac[3],
7377 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07007378 setKey.keyDirection);
7379
7380 vos_status = wlan_hdd_check_ula_done(pAdapter);
7381
7382 if ( vos_status != VOS_STATUS_SUCCESS )
7383 {
7384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7385 "[%4d] wlan_hdd_check_ula_done returned ERROR status= %d",
7386 __LINE__, vos_status );
7387
7388 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
7389
7390 return -EINVAL;
7391
7392 }
7393
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007394#ifdef WLAN_FEATURE_VOWIFI_11R
Gopichand Nakkala3d295922013-05-07 16:19:14 +05307395 /* The supplicant may attempt to set the PTK once pre-authentication
7396 is done. Save the key in the UMAC and include it in the ADD BSS
7397 request */
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007398 halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
Gopichand Nakkala3d295922013-05-07 16:19:14 +05307399 if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007400 {
Gopichand Nakkala3d295922013-05-07 16:19:14 +05307401 hddLog(VOS_TRACE_LEVEL_INFO_MED,
7402 "%s: Update PreAuth Key success", __func__);
7403 return 0;
7404 }
7405 else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
7406 {
7407 hddLog(VOS_TRACE_LEVEL_ERROR,
7408 "%s: Update PreAuth Key failed", __func__);
Gopichand Nakkalad7d13652013-02-15 01:48:00 +05307409 return -EINVAL;
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07007410 }
7411#endif /* WLAN_FEATURE_VOWIFI_11R */
Jeff Johnson295189b2012-06-20 16:38:30 -07007412
7413 /* issue set key request to SME*/
7414 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
7415 pAdapter->sessionId, &setKey, &roamId );
7416
7417 if ( 0 != status )
7418 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307419 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007420 "%s: sme_RoamSetKey failed, returned %d", __func__, status);
7421 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
7422 return -EINVAL;
7423 }
7424
7425
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307426 /* in case of IBSS as there was no information available about WEP keys during
7427 * IBSS join, group key intialized with NULL key, so re-initialize group key
Jeff Johnson295189b2012-06-20 16:38:30 -07007428 * with correct value*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307429 if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) &&
7430 !( ( IW_AUTH_KEY_MGMT_802_1X
7431 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
Jeff Johnson295189b2012-06-20 16:38:30 -07007432 && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)
7433 )
7434 &&
7435 ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher)
7436 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
7437 )
7438 )
7439 {
7440 setKey.keyDirection = eSIR_RX_ONLY;
7441 vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN);
7442
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307443 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07007444 "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307445 __func__, setKey.peerMac[0], setKey.peerMac[1],
7446 setKey.peerMac[2], setKey.peerMac[3],
7447 setKey.peerMac[4], setKey.peerMac[5],
Jeff Johnson295189b2012-06-20 16:38:30 -07007448 setKey.keyDirection);
7449
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307450 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 pAdapter->sessionId, &setKey, &roamId );
7452
7453 if ( 0 != status )
7454 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307455 hddLog(VOS_TRACE_LEVEL_ERROR,
7456 "%s: sme_RoamSetKey failed for group key (IBSS), returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07007457 __func__, status);
7458 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
7459 return -EINVAL;
7460 }
7461 }
7462 }
7463
7464 return 0;
7465}
7466
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7468static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
7469 struct net_device *ndev,
7470 u8 key_index, bool pairwise,
7471 const u8 *mac_addr,
7472 struct key_params *params
7473 )
7474#else
7475static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy,
7476 struct net_device *ndev,
7477 u8 key_index, const u8 *mac_addr,
7478 struct key_params *params
7479 )
7480#endif
7481{
7482 int ret;
7483 vos_ssr_protect(__func__);
7484#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7485 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
7486 mac_addr, params);
7487#else
7488 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, mac_addr,
7489 params);
7490#endif
7491 vos_ssr_unprotect(__func__);
7492
7493 return ret;
7494}
7495
Jeff Johnson295189b2012-06-20 16:38:30 -07007496/*
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307497 * FUNCTION: __wlan_hdd_cfg80211_get_key
Jeff Johnson295189b2012-06-20 16:38:30 -07007498 * This function is used to get the key information
7499 */
7500#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307501static int __wlan_hdd_cfg80211_get_key(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307502 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007503 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307504 u8 key_index, bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07007505 const u8 *mac_addr, void *cookie,
7506 void (*callback)(void *cookie, struct key_params*)
7507 )
7508#else
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307509static int __wlan_hdd_cfg80211_get_key(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307510 struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007511 struct net_device *ndev,
7512 u8 key_index, const u8 *mac_addr, void *cookie,
7513 void (*callback)(void *cookie, struct key_params*)
7514 )
7515#endif
7516{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307517 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05307518 hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7519 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
Jeff Johnson295189b2012-06-20 16:38:30 -07007520 struct key_params params;
7521
7522 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307523
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05307524 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
7525 __func__, hdd_device_modetoString(pAdapter->device_mode),
7526 pAdapter->device_mode);
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05307527
Jeff Johnson295189b2012-06-20 16:38:30 -07007528 memset(&params, 0, sizeof(params));
7529
7530 if (CSR_MAX_NUM_KEY <= key_index)
7531 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307532 hddLog(VOS_TRACE_LEVEL_ERROR, FL("invalid key index %d"), key_index);
Jeff Johnson295189b2012-06-20 16:38:30 -07007533 return -EINVAL;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307534 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007535
7536 switch(pRoamProfile->EncryptionType.encryptionType[0])
7537 {
7538 case eCSR_ENCRYPT_TYPE_NONE:
7539 params.cipher = IW_AUTH_CIPHER_NONE;
7540 break;
7541
7542 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
7543 case eCSR_ENCRYPT_TYPE_WEP40:
7544 params.cipher = WLAN_CIPHER_SUITE_WEP40;
7545 break;
7546
7547 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
7548 case eCSR_ENCRYPT_TYPE_WEP104:
7549 params.cipher = WLAN_CIPHER_SUITE_WEP104;
7550 break;
7551
7552 case eCSR_ENCRYPT_TYPE_TKIP:
7553 params.cipher = WLAN_CIPHER_SUITE_TKIP;
7554 break;
7555
7556 case eCSR_ENCRYPT_TYPE_AES:
7557 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
7558 break;
7559
7560 default:
7561 params.cipher = IW_AUTH_CIPHER_NONE;
7562 break;
7563 }
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05307564
c_hpothuaaf19692014-05-17 17:01:48 +05307565 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7566 TRACE_CODE_HDD_CFG80211_GET_KEY,
7567 pAdapter->sessionId, params.cipher));
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05307568
Jeff Johnson295189b2012-06-20 16:38:30 -07007569 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
7570 params.seq_len = 0;
7571 params.seq = NULL;
7572 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
7573 callback(cookie, &params);
7574 return 0;
7575}
7576
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307577#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7578static int wlan_hdd_cfg80211_get_key(
7579 struct wiphy *wiphy,
7580 struct net_device *ndev,
7581 u8 key_index, bool pairwise,
7582 const u8 *mac_addr, void *cookie,
7583 void (*callback)(void *cookie, struct key_params*)
7584 )
7585#else
7586static int wlan_hdd_cfg80211_get_key(
7587 struct wiphy *wiphy,
7588 struct net_device *ndev,
7589 u8 key_index, const u8 *mac_addr, void *cookie,
7590 void (*callback)(void *cookie, struct key_params*)
7591 )
7592#endif
7593{
7594 int ret;
7595
7596 vos_ssr_protect(__func__);
7597#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7598 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
7599 mac_addr, cookie, callback);
7600#else
7601 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, mac_addr,
7602 callback);
7603#endif
7604 vos_ssr_unprotect(__func__);
7605
7606 return ret;
7607}
7608
Jeff Johnson295189b2012-06-20 16:38:30 -07007609/*
7610 * FUNCTION: wlan_hdd_cfg80211_del_key
7611 * This function is used to delete the key information
7612 */
7613#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307614static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007615 struct net_device *ndev,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307616 u8 key_index,
7617 bool pairwise,
Jeff Johnson295189b2012-06-20 16:38:30 -07007618 const u8 *mac_addr
7619 )
7620#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307621static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007622 struct net_device *ndev,
7623 u8 key_index,
7624 const u8 *mac_addr
7625 )
7626#endif
7627{
7628 int status = 0;
7629
7630 //This code needs to be revisited. There is sme_removeKey API, we should
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307631 //plan to use that. After the change to use correct index in setkey,
Jeff Johnson295189b2012-06-20 16:38:30 -07007632 //it is observed that this is invalidating peer
7633 //key index whenever re-key is done. This is affecting data link.
7634 //It should be ok to ignore del_key.
7635#if 0
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307636 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
7637 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007638 u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
7639 tCsrRoamSetKey setKey;
7640 v_U32_t roamId= 0xFF;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307641
Jeff Johnson295189b2012-06-20 16:38:30 -07007642 ENTER();
7643
7644 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n",
7645 __func__,pAdapter->device_mode);
7646
7647 if (CSR_MAX_NUM_KEY <= key_index)
7648 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307649 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007650 key_index);
7651
7652 return -EINVAL;
7653 }
7654
7655 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
7656 setKey.keyId = key_index;
7657
7658 if (mac_addr)
7659 vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
7660 else
7661 vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN);
7662
7663 setKey.encType = eCSR_ENCRYPT_TYPE_NONE;
7664
7665 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07007666 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307667 )
7668 {
7669
7670 hdd_hostapd_state_t *pHostapdState =
Jeff Johnson295189b2012-06-20 16:38:30 -07007671 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7672 if( pHostapdState->bssState == BSS_START)
7673 {
7674 status = WLANSAP_SetKeySta( pVosContext, &setKey);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307675
Jeff Johnson295189b2012-06-20 16:38:30 -07007676 if ( status != eHAL_STATUS_SUCCESS )
7677 {
7678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7679 "[%4d] WLANSAP_SetKeySta returned ERROR status= %d",
7680 __LINE__, status );
7681 }
7682 }
7683 }
7684 else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307685 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Jeff Johnson295189b2012-06-20 16:38:30 -07007686 )
7687 {
7688 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7689
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307690 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
7691
7692 hddLog(VOS_TRACE_LEVEL_INFO_MED,
Jeff Johnson295189b2012-06-20 16:38:30 -07007693 "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x",
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307694 __func__, setKey.peerMac[0], setKey.peerMac[1],
7695 setKey.peerMac[2], setKey.peerMac[3],
Jeff Johnson295189b2012-06-20 16:38:30 -07007696 setKey.peerMac[4], setKey.peerMac[5]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307697 if(pAdapter->sessionCtx.station.conn_info.connState ==
7698 eConnectionState_Associated)
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307700 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07007701 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307702
Jeff Johnson295189b2012-06-20 16:38:30 -07007703 if ( 0 != status )
7704 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307705 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007706 "%s: sme_RoamSetKey failure, returned %d",
7707 __func__, status);
7708 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
7709 return -EINVAL;
7710 }
7711 }
7712 }
7713#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007714 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07007715 return status;
7716}
7717
7718/*
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307719 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
Jeff Johnson295189b2012-06-20 16:38:30 -07007720 * This function is used to set the default tx key index
7721 */
7722#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307723static int __wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007724 struct net_device *ndev,
7725 u8 key_index,
7726 bool unicast, bool multicast)
7727#else
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307728static int __wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07007729 struct net_device *ndev,
7730 u8 key_index)
7731#endif
7732{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307733 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307734 int status;
Gopichand Nakkala29149562013-05-10 21:43:41 +05307735 hdd_wext_state_t *pWextState;
7736 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307737 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007738
7739 ENTER();
7740
Gopichand Nakkala29149562013-05-10 21:43:41 +05307741 if ((NULL == pAdapter))
7742 {
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05307743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Gopichand Nakkala29149562013-05-10 21:43:41 +05307744 "invalid adapter");
7745 return -EINVAL;
7746 }
7747
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307748 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
7749 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
7750 pAdapter->sessionId, key_index));
7751
Gopichand Nakkala29149562013-05-10 21:43:41 +05307752 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7753 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7754
7755 if ((NULL == pWextState) || (NULL == pHddStaCtx))
7756 {
7757 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7758 "invalid Wext state or HDD context");
7759 return -EINVAL;
7760 }
7761
Arif Hussain6d2a3322013-11-17 19:50:10 -08007762 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07007763 __func__,pAdapter->device_mode, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307764
Jeff Johnson295189b2012-06-20 16:38:30 -07007765 if (CSR_MAX_NUM_KEY <= key_index)
7766 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307767 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007768 key_index);
7769
7770 return -EINVAL;
7771 }
7772
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307773 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7774 status = wlan_hdd_validate_context(pHddCtx);
7775
7776 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007777 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05307778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7779 "%s: HDD context is not valid", __func__);
7780 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07007781 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307782
Jeff Johnson295189b2012-06-20 16:38:30 -07007783 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
Jeff Johnson295189b2012-06-20 16:38:30 -07007784 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307785 )
Jeff Johnson295189b2012-06-20 16:38:30 -07007786 {
Gopichand Nakkala29149562013-05-10 21:43:41 +05307787 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
Arif Hussain6943f522013-11-04 20:10:10 -08007788 pHddStaCtx->conn_info.ucEncryptionType) &&
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307789 (eCSR_ENCRYPT_TYPE_AES !=
Arif Hussain6943f522013-11-04 20:10:10 -08007790 pHddStaCtx->conn_info.ucEncryptionType)
Jeff Johnson295189b2012-06-20 16:38:30 -07007791 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307792 {
7793 /* if default key index is not same as previous one,
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 * then update the default key index */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307795
Jeff Johnson295189b2012-06-20 16:38:30 -07007796 tCsrRoamSetKey setKey;
7797 v_U32_t roamId= 0xFF;
7798 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307799
7800 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07007801 __func__, key_index);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307802
Jeff Johnson295189b2012-06-20 16:38:30 -07007803 Keys->defaultIndex = (u8)key_index;
7804 vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
7805 setKey.keyId = key_index;
7806 setKey.keyLength = Keys->KeyLength[key_index];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307807
7808 vos_mem_copy(&setKey.Key[0],
7809 &Keys->KeyMaterial[key_index][0],
Jeff Johnson295189b2012-06-20 16:38:30 -07007810 Keys->KeyLength[key_index]);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307811
Gopichand Nakkala29149562013-05-10 21:43:41 +05307812 setKey.keyDirection = eSIR_TX_RX;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307813
7814 vos_mem_copy(setKey.peerMac,
Jeff Johnson295189b2012-06-20 16:38:30 -07007815 &pHddStaCtx->conn_info.bssId[0],
7816 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307817
Gopichand Nakkala29149562013-05-10 21:43:41 +05307818 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
7819 pWextState->roamProfile.EncryptionType.encryptionType[0] ==
7820 eCSR_ENCRYPT_TYPE_WEP104)
7821 {
7822 /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104
7823 even though ap is configured for WEP-40 encryption. In this canse the key length
7824 is 5 but the encryption type is 104 hence checking the key langht(5) and encryption
7825 type(104) and switching encryption type to 40*/
7826 pWextState->roamProfile.EncryptionType.encryptionType[0] =
7827 eCSR_ENCRYPT_TYPE_WEP40;
7828 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
7829 eCSR_ENCRYPT_TYPE_WEP40;
7830 }
7831
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307832 setKey.encType =
Jeff Johnson295189b2012-06-20 16:38:30 -07007833 pWextState->roamProfile.EncryptionType.encryptionType[0];
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307834
Jeff Johnson295189b2012-06-20 16:38:30 -07007835 /* issue set key request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307836 status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07007837 pAdapter->sessionId, &setKey, &roamId );
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307838
Jeff Johnson295189b2012-06-20 16:38:30 -07007839 if ( 0 != status )
7840 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307841 hddLog(VOS_TRACE_LEVEL_ERROR,
7842 "%s: sme_RoamSetKey failed, returned %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07007843 status);
7844 return -EINVAL;
7845 }
7846 }
7847 }
7848
7849 /* In SoftAp mode setting key direction for default mode */
7850 else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
7851 {
7852 if ( (eCSR_ENCRYPT_TYPE_TKIP !=
7853 pWextState->roamProfile.EncryptionType.encryptionType[0]) &&
7854 (eCSR_ENCRYPT_TYPE_AES !=
7855 pWextState->roamProfile.EncryptionType.encryptionType[0])
7856 )
7857 {
7858 /* Saving key direction for default key index to TX default */
7859 hdd_ap_ctx_t *pAPCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7860 pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT;
7861 }
7862 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307863
Jeff Johnson295189b2012-06-20 16:38:30 -07007864 return status;
7865}
7866
Mahesh A Saptasagar1a51bc02014-06-02 18:28:08 +05307867#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7868static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
7869 struct net_device *ndev,
7870 u8 key_index,
7871 bool unicast, bool multicast)
7872#else
7873static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy,
7874 struct net_device *ndev,
7875 u8 key_index)
7876#endif
7877{
7878 int ret;
7879 vos_ssr_protect(__func__);
7880#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
7881 ret = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
7882 multicast);
7883#else
7884 ret = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index);
7885#endif
7886 vos_ssr_unprotect(__func__);
7887
7888 return ret;
7889}
7890
Jeff Johnson295189b2012-06-20 16:38:30 -07007891/*
7892 * FUNCTION: wlan_hdd_cfg80211_inform_bss
7893 * This function is used to inform the BSS details to nl80211 interface.
7894 */
7895static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss(
7896 hdd_adapter_t *pAdapter, tCsrRoamConnectedProfile *roamProfile)
7897{
7898 struct net_device *dev = pAdapter->dev;
7899 struct wireless_dev *wdev = dev->ieee80211_ptr;
7900 struct wiphy *wiphy = wdev->wiphy;
7901 tSirBssDescription *pBssDesc = roamProfile->pBssDesc;
7902 int chan_no;
7903 int ie_length;
7904 const char *ie;
7905 unsigned int freq;
7906 struct ieee80211_channel *chan;
7907 int rssi = 0;
7908 struct cfg80211_bss *bss = NULL;
7909
7910 ENTER();
7911
7912 if( NULL == pBssDesc )
7913 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007914 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pBssDesc is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007915 return bss;
7916 }
7917
7918 chan_no = pBssDesc->channelId;
7919 ie_length = GET_IE_LEN_IN_BSS_DESC( pBssDesc->length );
7920 ie = ((ie_length != 0) ? (const char *)&pBssDesc->ieFields: NULL);
7921
7922 if( NULL == ie )
7923 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007924 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: IE of BSS descriptor is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007925 return bss;
7926 }
7927
7928#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
7929 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ))
7930 {
7931 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
7932 }
7933 else
7934 {
7935 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
7936 }
7937#else
7938 freq = ieee80211_channel_to_frequency(chan_no);
7939#endif
7940
7941 chan = __ieee80211_get_channel(wiphy, freq);
7942
Santhosh Kumar Padmaa45fdb12014-04-15 15:54:38 +05307943 if (!chan) {
7944 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
7945 return NULL;
7946 }
7947
Abhishek Singhaee43942014-06-16 18:55:47 +05307948 rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100;
Jeff Johnson295189b2012-06-20 16:38:30 -07007949
Abhishek Singhaee43942014-06-16 18:55:47 +05307950 return cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05307951 le64_to_cpu(*(__le64 *)pBssDesc->timeStamp),
Jeff Johnson295189b2012-06-20 16:38:30 -07007952 pBssDesc->capabilityInfo,
7953 pBssDesc->beaconInterval, ie, ie_length,
Abhishek Singhaee43942014-06-16 18:55:47 +05307954 rssi, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07007955}
7956
7957
7958
7959/*
7960 * FUNCTION: wlan_hdd_cfg80211_inform_bss_frame
7961 * This function is used to inform the BSS details to nl80211 interface.
7962 */
7963struct cfg80211_bss*
7964wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter,
7965 tSirBssDescription *bss_desc
7966 )
7967{
7968 /*
7969 cfg80211_inform_bss() is not updating ie field of bss entry, if entry
7970 already exists in bss data base of cfg80211 for that particular BSS ID.
7971 Using cfg80211_inform_bss_frame to update the bss entry instead of
7972 cfg80211_inform_bss, But this call expects mgmt packet as input. As of
7973 now there is no possibility to get the mgmt(probe response) frame from PE,
7974 converting bss_desc to ieee80211_mgmt(probe response) and passing to
7975 cfg80211_inform_bss_frame.
7976 */
7977 struct net_device *dev = pAdapter->dev;
7978 struct wireless_dev *wdev = dev->ieee80211_ptr;
7979 struct wiphy *wiphy = wdev->wiphy;
7980 int chan_no = bss_desc->channelId;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08007981#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7982 qcom_ie_age *qie_age = NULL;
7983 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length ) + sizeof(qcom_ie_age);
7984#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007985 int ie_length = GET_IE_LEN_IN_BSS_DESC( bss_desc->length );
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08007986#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007987 const char *ie =
7988 ((ie_length != 0) ? (const char *)&bss_desc->ieFields: NULL);
7989 unsigned int freq;
7990 struct ieee80211_channel *chan;
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05307991 struct ieee80211_mgmt *mgmt = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007992 struct cfg80211_bss *bss_status = NULL;
7993 size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length;
7994 int rssi = 0;
Wilson Yangf80a0542013-10-07 13:02:37 -07007995 hdd_context_t *pHddCtx;
7996 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07007997#ifdef WLAN_OPEN_SOURCE
7998 struct timespec ts;
7999#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008000
Wilson Yangf80a0542013-10-07 13:02:37 -07008001 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8002 status = wlan_hdd_validate_context(pHddCtx);
8003
8004 /*bss_update is not allowed during wlan driver loading or unloading*/
Mihir Shete18156292014-03-11 15:38:30 +05308005 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Wilson Yangf80a0542013-10-07 13:02:37 -07008006 {
8007 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8008 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
8009 return NULL;
8010 }
8011
8012
8013 if (0 != status)
8014 {
8015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8016 "%s: HDD context is not valid", __func__);
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07008017 return NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07008018 }
8019
Abhishek Singh1e2bfa32014-01-02 15:44:15 +05308020 mgmt = kzalloc((sizeof (struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
Wilson Yangf80a0542013-10-07 13:02:37 -07008021 if (!mgmt)
8022 {
8023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8024 "%s: memory allocation failed ", __func__);
8025 return NULL;
8026 }
Madan Mohan Koyyalamudi2e5c9142012-11-02 13:17:48 -07008027
Jeff Johnson295189b2012-06-20 16:38:30 -07008028 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07008029
8030#ifdef WLAN_OPEN_SOURCE
8031 /* Android does not want the timestamp from the frame.
8032 Instead it wants a monotonic increasing value */
8033 get_monotonic_boottime(&ts);
8034 mgmt->u.probe_resp.timestamp =
8035 ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
8036#else
8037 /* keep old behavior for non-open source (for now) */
Jeff Johnson295189b2012-06-20 16:38:30 -07008038 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
8039 sizeof (bss_desc->timeStamp));
Jeff Johnsone7245742012-09-05 17:12:55 -07008040
8041#endif
8042
Jeff Johnson295189b2012-06-20 16:38:30 -07008043 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
8044 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
Madan Mohan Koyyalamudi86f629e2012-11-09 16:27:29 -08008045
8046#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
8047 /* GPS Requirement: need age ie per entry. Using vendor specific. */
8048 /* Assuming this is the last IE, copy at the end */
8049 ie_length -=sizeof(qcom_ie_age);
8050 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + ie_length);
8051 qie_age->element_id = QCOM_VENDOR_IE_ID;
8052 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
8053 qie_age->oui_1 = QCOM_OUI1;
8054 qie_age->oui_2 = QCOM_OUI2;
8055 qie_age->oui_3 = QCOM_OUI3;
8056 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
8057 qie_age->age = vos_timer_get_system_ticks() - bss_desc->nReceivedTime;
8058#endif
8059
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
Gopichand Nakkalad908ec82013-05-16 19:32:19 +05308061 if (bss_desc->fProbeRsp)
8062 {
8063 mgmt->frame_control |=
8064 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
8065 }
8066 else
8067 {
8068 mgmt->frame_control |=
8069 (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
8070 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008071
8072#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308073 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07008074 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL))
8075 {
8076 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ);
8077 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308078 else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) &&
Jeff Johnson295189b2012-06-20 16:38:30 -07008079 (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL))
8080
8081 {
8082 freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_5GHZ);
8083 }
8084 else
8085 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05308086 hddLog(VOS_TRACE_LEVEL_ERROR, "%s Invalid chan_no:%d",
8087 __func__, chan_no);
Jeff Johnson295189b2012-06-20 16:38:30 -07008088 kfree(mgmt);
8089 return NULL;
8090 }
8091#else
8092 freq = ieee80211_channel_to_frequency(chan_no);
8093#endif
8094 chan = __ieee80211_get_channel(wiphy, freq);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08008095 /*when the band is changed on the fly using the GUI, three things are done
8096 * 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)
8097 * as part of the scan abort, message willbe queued to PE and we proceed with flushing and changinh the band.
8098 * pe will stop the scanning further and report back the results what ever it had till now by calling the call back function.
8099 * if the time between update band and scandone call back is sufficent enough the band change reflects in SME, SME validates the channels
8100 * and discards the channels correponding to previous band and calls back with zero bss results.
8101 * 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
8102 * all the channels correponding to previous band.this is due to race condition.but those channels are invalid to the new band and so
8103 * this function __ieee80211_get_channel will return NULL.Each time we report scan result with this pointer null warning kernel trace is printed.
8104 * if the scan results contain large number of APs continuosly kernel warning trace is printed and it will lead to apps watch dog bark.
8105 * So drop the bss and continue to next bss.
8106 */
8107 if(chan == NULL)
8108 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05308109 hddLog(VOS_TRACE_LEVEL_ERROR, "%s chan pointer is NULL", __func__);
Chilam Ngc4244af2013-04-01 15:37:32 -07008110 kfree(mgmt);
Leela V Kiran Kumar Reddy90032de2013-01-24 18:33:30 -08008111 return NULL;
8112 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008113 /*To keep the rssi icon of the connected AP in the scan window
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308114 *and the rssi icon of the wireless networks in sync
Jeff Johnson295189b2012-06-20 16:38:30 -07008115 * */
8116 if (( eConnectionState_Associated ==
8117 pAdapter->sessionCtx.station.conn_info.connState ) &&
8118 ( VOS_TRUE == vos_mem_compare(bss_desc->bssId,
8119 pAdapter->sessionCtx.station.conn_info.bssId,
8120 WNI_CFG_BSSID_LEN)))
8121 {
8122 /* supplicant takes the signal strength in terms of mBm(100*dBm) */
8123 rssi = (pAdapter->rssi * 100);
8124 }
8125 else
8126 {
8127 rssi = (VOS_MIN ((bss_desc->rssi + bss_desc->sinr), 0))*100;
8128 }
8129
Nirav Shah20ac06f2013-12-12 18:14:06 +05308130 hddLog(VOS_TRACE_LEVEL_INFO, "%s: BSSID:" MAC_ADDRESS_STR " Channel:%d"
8131 "RSSI:%d", __func__, MAC_ADDR_ARRAY(mgmt->bssid),
8132 chan->center_freq, (int)(rssi/100));
8133
Jeff Johnson295189b2012-06-20 16:38:30 -07008134 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt,
8135 frame_len, rssi, GFP_KERNEL);
8136 kfree(mgmt);
8137 return bss_status;
8138}
8139
8140/*
8141 * FUNCTION: wlan_hdd_cfg80211_update_bss_db
8142 * This function is used to update the BSS data base of CFG8011
8143 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308144struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07008145 tCsrRoamInfo *pRoamInfo
8146 )
8147{
8148 tCsrRoamConnectedProfile roamProfile;
8149 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8150 struct cfg80211_bss *bss = NULL;
8151
8152 ENTER();
8153
8154 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
8155 sme_RoamGetConnectProfile(hHal, pAdapter->sessionId, &roamProfile);
8156
8157 if (NULL != roamProfile.pBssDesc)
8158 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308159 bss = wlan_hdd_cfg80211_inform_bss(pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07008160 &roamProfile);
8161
8162 if (NULL == bss)
8163 {
8164 hddLog(VOS_TRACE_LEVEL_INFO, "%s: cfg80211_inform_bss return NULL",
8165 __func__);
8166 }
8167
8168 sme_RoamFreeConnectProfile(hHal, &roamProfile);
8169 }
8170 else
8171 {
8172 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: roamProfile.pBssDesc is NULL",
8173 __func__);
8174 }
8175 return bss;
8176}
8177
8178/*
8179 * FUNCTION: wlan_hdd_cfg80211_update_bss
8180 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308181static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy,
8182 hdd_adapter_t *pAdapter
Jeff Johnson295189b2012-06-20 16:38:30 -07008183 )
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308184{
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05308185 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008186 tCsrScanResultInfo *pScanResult;
8187 eHalStatus status = 0;
8188 tScanResultHandle pResult;
8189 struct cfg80211_bss *bss_status = NULL;
Wilson Yangf80a0542013-10-07 13:02:37 -07008190 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07008191
8192 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05308193
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05308194 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
8195 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
8196 NO_SESSION, pAdapter->sessionId));
8197
Wilson Yangf80a0542013-10-07 13:02:37 -07008198 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8199
8200 if (pHddCtx->isLogpInProgress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008201 {
Wilson Yangf80a0542013-10-07 13:02:37 -07008202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8203 "%s:LOGP in Progress. Ignore!!!",__func__);
8204 return -EAGAIN;
Jeff Johnson295189b2012-06-20 16:38:30 -07008205 }
8206
Wilson Yangf80a0542013-10-07 13:02:37 -07008207
8208 /*bss_update is not allowed during wlan driver loading or unloading*/
Mihir Shete18156292014-03-11 15:38:30 +05308209 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Wilson Yangf80a0542013-10-07 13:02:37 -07008210 {
8211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8212 "%s:Loading_unloading in Progress. Ignore!!!",__func__);
8213 return VOS_STATUS_E_PERM;
8214 }
8215
8216
Jeff Johnson295189b2012-06-20 16:38:30 -07008217 /*
8218 * start getting scan results and populate cgf80211 BSS database
8219 */
8220 status = sme_ScanGetResult(hHal, pAdapter->sessionId, NULL, &pResult);
8221
8222 /* no scan results */
8223 if (NULL == pResult)
8224 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05308225 hddLog(VOS_TRACE_LEVEL_INFO, "%s: No scan result Status %d",
8226 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008227 return status;
8228 }
8229
8230 pScanResult = sme_ScanResultGetFirst(hHal, pResult);
8231
8232 while (pScanResult)
8233 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308234 /*
8235 * cfg80211_inform_bss() is not updating ie field of bss entry, if
8236 * entry already exists in bss data base of cfg80211 for that
8237 * particular BSS ID. Using cfg80211_inform_bss_frame to update the
8238 * bss entry instead of cfg80211_inform_bss, But this call expects
8239 * mgmt packet as input. As of now there is no possibility to get
8240 * the mgmt(probe response) frame from PE, converting bss_desc to
Jeff Johnson295189b2012-06-20 16:38:30 -07008241 * ieee80211_mgmt(probe response) and passing to c
8242 * fg80211_inform_bss_frame.
8243 * */
8244
8245 bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
8246 &pScanResult->BssDescriptor);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308247
Jeff Johnson295189b2012-06-20 16:38:30 -07008248
8249 if (NULL == bss_status)
8250 {
8251 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008252 "%s: NULL returned by cfg80211_inform_bss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008253 }
8254 else
8255 {
Yue Maf49ba872013-08-19 12:04:25 -07008256 cfg80211_put_bss(
8257#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
8258 wiphy,
8259#endif
8260 bss_status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008261 }
8262
8263 pScanResult = sme_ScanResultGetNext(hHal, pResult);
8264 }
8265
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308266 sme_ScanResultPurge(hHal, pResult);
Jeff Johnson295189b2012-06-20 16:38:30 -07008267
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308268 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008269}
8270
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008271void
8272hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel)
8273{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308274 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussaina7c8e412013-11-20 11:06:42 -08008275 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(macAddr));
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008276} /****** end hddPrintMacAddr() ******/
8277
8278void
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07008279hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008280{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308281 VOS_TRACE(VOS_MODULE_ID_HDD, logLevel,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008282 "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07008283 pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4],
8284 pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10],
8285 pmkId[11], pmkId[12], pmkId[13], pmkId[14], pmkId[15]);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008286} /****** end hddPrintPmkId() ******/
8287
8288//hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel);
8289//hddPrintMacAddr(macAddr, VOS_TRACE_LEVEL_FATAL);
8290
8291//void sirDumpBuf(tpAniSirGlobal pMac, tANI_U8 modId, tANI_U32 level, tANI_U8 *buf, tANI_U32 size);
8292//sirDumpBuf(pMac, VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, pmkid, 16);
8293
8294#define dump_bssid(bssid) \
8295 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07008296 hddLog(VOS_TRACE_LEVEL_INFO, "BSSID (MAC) address:\t"); \
8297 hddPrintMacAddr(bssid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008298 }
8299
8300#define dump_pmkid(pMac, pmkid) \
8301 { \
Jeff Johnsone7245742012-09-05 17:12:55 -07008302 hddLog(VOS_TRACE_LEVEL_INFO, "PMKSA-ID:\t"); \
8303 hddPrintPmkId(pmkid, VOS_TRACE_LEVEL_INFO);\
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008304 }
8305
Madan Mohan Koyyalamudi1b4afb02012-10-22 15:25:16 -07008306#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008307/*
8308 * FUNCTION: wlan_hdd_cfg80211_pmksa_candidate_notify
8309 * This function is used to notify the supplicant of a new PMKSA candidate.
8310 */
8311int wlan_hdd_cfg80211_pmksa_candidate_notify(
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308312 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008313 int index, bool preauth )
8314{
Jeff Johnsone7245742012-09-05 17:12:55 -07008315#ifdef FEATURE_WLAN_OKC
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008316 struct net_device *dev = pAdapter->dev;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07008317 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008318
8319 ENTER();
Jeff Johnsone7245742012-09-05 17:12:55 -07008320 hddLog(VOS_TRACE_LEVEL_INFO, "%s is going to notify supplicant of:", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008321
8322 if( NULL == pRoamInfo )
8323 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008324 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: pRoamInfo is NULL", __func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008325 return -EINVAL;
8326 }
8327
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07008328 if (eANI_BOOLEAN_TRUE == hdd_is_okc_mode_enabled(pHddCtx))
8329 {
8330 dump_bssid(pRoamInfo->bssid);
8331 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008332 pRoamInfo->bssid, preauth, GFP_KERNEL);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07008333 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008334#endif /* FEATURE_WLAN_OKC */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308335 return 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07008336}
8337#endif //FEATURE_WLAN_LFR
8338
Yue Maef608272013-04-08 23:09:17 -07008339#ifdef FEATURE_WLAN_LFR_METRICS
8340/*
8341 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth
8342 * 802.11r/LFR metrics reporting function to report preauth initiation
8343 *
8344 */
8345#define MAX_LFR_METRICS_EVENT_LENGTH 100
8346VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
8347 tCsrRoamInfo *pRoamInfo)
8348{
8349 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8350 union iwreq_data wrqu;
8351
8352 ENTER();
8353
8354 if (NULL == pAdapter)
8355 {
8356 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
8357 return VOS_STATUS_E_FAILURE;
8358 }
8359
8360 /* create the event */
8361 memset(&wrqu, 0, sizeof(wrqu));
8362 memset(metrics_notification, 0, sizeof(metrics_notification));
8363
8364 wrqu.data.pointer = metrics_notification;
8365 wrqu.data.length = scnprintf(metrics_notification,
8366 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_INIT "
8367 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
8368
8369 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
8370
8371 EXIT();
8372
8373 return VOS_STATUS_SUCCESS;
8374}
8375
8376/*
8377 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_preauth_status
8378 * 802.11r/LFR metrics reporting function to report preauth completion
8379 * or failure
8380 */
8381VOS_STATUS wlan_hdd_cfg80211_roam_metrics_preauth_status(
8382 hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, bool preauth_status)
8383{
8384 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8385 union iwreq_data wrqu;
8386
8387 ENTER();
8388
8389 if (NULL == pAdapter)
8390 {
8391 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
8392 return VOS_STATUS_E_FAILURE;
8393 }
8394
8395 /* create the event */
8396 memset(&wrqu, 0, sizeof(wrqu));
8397 memset(metrics_notification, 0, sizeof(metrics_notification));
8398
8399 scnprintf(metrics_notification, sizeof(metrics_notification),
8400 "QCOM: LFR_PREAUTH_STATUS "MAC_ADDRESS_STR,
8401 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8402
8403 if (1 == preauth_status)
8404 strncat(metrics_notification, " TRUE", 5);
8405 else
8406 strncat(metrics_notification, " FALSE", 6);
8407
8408 wrqu.data.pointer = metrics_notification;
8409 wrqu.data.length = strlen(metrics_notification);
8410
8411 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
8412
8413 EXIT();
8414
8415 return VOS_STATUS_SUCCESS;
8416}
8417
8418/*
8419 * FUNCTION: wlan_hdd_cfg80211_roam_metrics_handover
8420 * 802.11r/LFR metrics reporting function to report handover initiation
8421 *
8422 */
8423VOS_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t * pAdapter,
8424 tCsrRoamInfo *pRoamInfo)
8425{
8426 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8427 union iwreq_data wrqu;
8428
8429 ENTER();
8430
8431 if (NULL == pAdapter)
8432 {
8433 hddLog(LOGE, "%s: pAdapter is NULL!", __func__);
8434 return VOS_STATUS_E_FAILURE;
8435 }
8436
8437 /* create the event */
8438 memset(&wrqu, 0, sizeof(wrqu));
8439 memset(metrics_notification, 0, sizeof(metrics_notification));
8440
8441 wrqu.data.pointer = metrics_notification;
8442 wrqu.data.length = scnprintf(metrics_notification,
8443 sizeof(metrics_notification), "QCOM: LFR_PREAUTH_HANDOVER "
8444 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pRoamInfo->bssid));
8445
8446 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, metrics_notification);
8447
8448 EXIT();
8449
8450 return VOS_STATUS_SUCCESS;
8451}
8452#endif
8453
Jeff Johnson295189b2012-06-20 16:38:30 -07008454/*
8455 * FUNCTION: hdd_cfg80211_scan_done_callback
8456 * scanning callback function, called after finishing scan
8457 *
8458 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308459static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle,
Jeff Johnson295189b2012-06-20 16:38:30 -07008460 void *pContext, tANI_U32 scanId, eCsrScanStatus status)
8461{
8462 struct net_device *dev = (struct net_device *) pContext;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308463 //struct wireless_dev *wdev = dev->ieee80211_ptr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008465 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8466 hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07008467 struct cfg80211_scan_request *req = NULL;
8468 int ret = 0;
Mahesh A Saptasagar05a357e2014-02-26 16:28:06 +05308469 bool aborted = false;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308470 long waitRet = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008471
8472 ENTER();
8473
8474 hddLog(VOS_TRACE_LEVEL_INFO,
8475 "%s called with halHandle = %p, pContext = %p,"
Arif Hussain6d2a3322013-11-17 19:50:10 -08008476 "scanID = %d, returned status = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07008477 __func__, halHandle, pContext, (int) scanId, (int) status);
8478
Kiet Lamac06e2c2013-10-23 16:25:07 +05308479 pScanInfo->mScanPendingCounter = 0;
8480
Jeff Johnson295189b2012-06-20 16:38:30 -07008481 //Block on scan req completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308482 waitRet = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008483 &pScanInfo->scan_req_completion_event,
8484 msecs_to_jiffies(WLAN_WAIT_TIME_SCAN_REQ));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308485 if (waitRet <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008486 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308487 hddLog(VOS_TRACE_LEVEL_ERROR,
8488 "%s wait on scan_req_completion_event failed %ld",__func__, waitRet);
Jeff Johnson295189b2012-06-20 16:38:30 -07008489 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07008490 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07008491 }
8492
Yue Maef608272013-04-08 23:09:17 -07008493 if (pScanInfo->mScanPending != VOS_TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -07008494 {
8495 VOS_ASSERT(pScanInfo->mScanPending);
Jeff Johnsone7245742012-09-05 17:12:55 -07008496 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07008497 }
8498
8499 /* Check the scanId */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308500 if (pScanInfo->scanId != scanId)
Jeff Johnson295189b2012-06-20 16:38:30 -07008501 {
8502 hddLog(VOS_TRACE_LEVEL_INFO,
8503 "%s called with mismatched scanId pScanInfo->scanId = %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08008504 "scanId = %d", __func__, (int) pScanInfo->scanId,
Jeff Johnson295189b2012-06-20 16:38:30 -07008505 (int) scanId);
8506 }
8507
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308508 ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07008509 pAdapter);
8510
8511 if (0 > ret)
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308512 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008513
8514
8515 /* If any client wait scan result through WEXT
8516 * send scan done event to client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008517 if (pHddCtx->scan_info.waitScanResult)
Jeff Johnson295189b2012-06-20 16:38:30 -07008518 {
8519 /* The other scan request waiting for current scan finish
8520 * Send event to notify current scan finished */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008521 if(WEXT_SCAN_PENDING_DELAY == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07008522 {
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008523 vos_event_set(&pHddCtx->scan_info.scan_finished_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07008524 }
8525 /* Send notify to WEXT client */
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008526 else if(WEXT_SCAN_PENDING_PIGGYBACK == pHddCtx->scan_info.scan_pending_option)
Jeff Johnson295189b2012-06-20 16:38:30 -07008527 {
8528 struct net_device *dev = pAdapter->dev;
8529 union iwreq_data wrqu;
8530 int we_event;
8531 char *msg;
8532
8533 memset(&wrqu, '\0', sizeof(wrqu));
8534 we_event = SIOCGIWSCAN;
8535 msg = NULL;
8536 wireless_send_event(dev, we_event, &wrqu, msg);
8537 }
8538 }
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008539 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008540
8541 /* Get the Scan Req */
8542 req = pAdapter->request;
8543
8544 if (!req)
8545 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008546 hddLog(VOS_TRACE_LEVEL_ERROR, "request is became NULL");
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07008547 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnsone7245742012-09-05 17:12:55 -07008548 goto allow_suspend;
Jeff Johnson295189b2012-06-20 16:38:30 -07008549 }
8550
8551 /*
8552 * setting up 0, just in case.
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308553 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008554 req->n_ssids = 0;
8555 req->n_channels = 0;
8556 req->ie = 0;
8557
Jeff Johnson295189b2012-06-20 16:38:30 -07008558 pAdapter->request = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008559 /* Scan is no longer pending */
8560 pScanInfo->mScanPending = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008561
Madan Mohan Koyyalamudib764bf82012-10-11 16:38:51 -07008562 /*
8563 * cfg80211_scan_done informing NL80211 about completion
8564 * of scanning
8565 */
Mahesh A Saptasagar05a357e2014-02-26 16:28:06 +05308566 if (status == eCSR_SCAN_ABORT || status == eCSR_SCAN_FAILURE)
8567 {
8568 aborted = true;
8569 }
8570 cfg80211_scan_done(req, aborted);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008571 complete(&pScanInfo->abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07008572
Jeff Johnsone7245742012-09-05 17:12:55 -07008573allow_suspend:
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07008574 /* release the wake lock at the end of the scan*/
8575 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07008576
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008577 /* Acquire wakelock to handle the case where APP's tries to suspend
8578 * immediatly after the driver gets connect request(i.e after scan)
8579 * from supplicant, this result in app's is suspending and not able
8580 * to process the connect request to AP */
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308581 hdd_prevent_suspend_timeout(1000);
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008582
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07008583#ifdef FEATURE_WLAN_TDLS
c_hpothu3c8f8e82014-06-02 18:01:50 +05308584 if (!(eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode))
8585 {
8586 wlan_hdd_tdls_scan_done_callback(pAdapter);
8587 }
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07008588#endif
8589
Jeff Johnson295189b2012-06-20 16:38:30 -07008590 EXIT();
8591 return 0;
8592}
8593
8594/*
Rashmi Ramannab1429032014-04-26 14:59:09 +05308595 * FUNCTION: hdd_isConnectionInProgress
8596 * Go through each adapter and check if Connection is in progress
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008597 *
8598 */
Rashmi Ramannab1429032014-04-26 14:59:09 +05308599v_BOOL_t hdd_isConnectionInProgress( hdd_context_t *pHddCtx )
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008600{
8601 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8602 hdd_station_ctx_t *pHddStaCtx = NULL;
8603 hdd_adapter_t *pAdapter = NULL;
8604 VOS_STATUS status = 0;
8605 v_U8_t staId = 0;
8606 v_U8_t *staMac = NULL;
8607
c_hpothu9b781ba2013-12-30 20:57:45 +05308608 if (TRUE == pHddCtx->btCoexModeSet)
8609 {
8610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Rashmi Ramannab1429032014-04-26 14:59:09 +05308611 FL("BTCoex Mode operation in progress"));
8612 return VOS_TRUE;
c_hpothu9b781ba2013-12-30 20:57:45 +05308613 }
8614
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8616
8617 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8618 {
8619 pAdapter = pAdapterNode->pAdapter;
8620
8621 if( pAdapter )
8622 {
8623 hddLog(VOS_TRACE_LEVEL_INFO,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05308624 "%s: Adapter with device mode %s (%d) exists",
8625 __func__, hdd_device_modetoString(pAdapter->device_mode),
8626 pAdapter->device_mode);
Rashmi Ramannab1429032014-04-26 14:59:09 +05308627 if (((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8628 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
8629 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)) &&
8630 (eConnectionState_Connecting ==
8631 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
8632 {
8633 hddLog(VOS_TRACE_LEVEL_ERROR,
8634 "%s: %p(%d) Connection is in progress", __func__,
8635 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pAdapter->sessionId);
8636 return VOS_TRUE;
8637 }
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008638 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05308639 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
8640 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008641 {
8642 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8643 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05308644 (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated))
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008645 {
8646 staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]);
8647 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08008648 "%s: client " MAC_ADDRESS_STR
8649 " is in the middle of WPS/EAPOL exchange.", __func__,
8650 MAC_ADDR_ARRAY(staMac));
Rashmi Ramannab1429032014-04-26 14:59:09 +05308651 return VOS_TRUE;
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008652 }
8653 }
8654 else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
8655 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
8656 {
8657 for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++)
8658 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308659 if ((pAdapter->aStaInfo[staId].isUsed) &&
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008660 (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState))
8661 {
8662 staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]);
8663
8664 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain24bafea2013-11-15 15:10:03 -08008665 "%s: client " MAC_ADDRESS_STR " of SoftAP/P2P-GO is in the "
8666 "middle of WPS/EAPOL exchange.", __func__,
8667 MAC_ADDR_ARRAY(staMac));
Rashmi Ramannab1429032014-04-26 14:59:09 +05308668 return VOS_TRUE;
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008669 }
8670 }
8671 }
8672 }
8673 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8674 pAdapterNode = pNext;
8675 }
Rashmi Ramannab1429032014-04-26 14:59:09 +05308676 return VOS_FALSE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308677}
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008678
8679/*
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +05308680 * FUNCTION: __wlan_hdd_cfg80211_scan
Jeff Johnson295189b2012-06-20 16:38:30 -07008681 * this scan respond to scan trigger and update cfg80211 scan database
8682 * later, scan dump command can be used to recieve scan results
8683 */
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +05308684int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08008685#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
8686 struct net_device *dev,
8687#endif
8688 struct cfg80211_scan_request *request)
8689{
Siddharth Bhal0c162d02014-05-06 19:50:42 +05308690 hdd_adapter_t *pAdapter = NULL;
8691 hdd_context_t *pHddCtx = NULL;
8692 hdd_wext_state_t *pwextBuf = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308693 hdd_config_t *cfg_param = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008694 tCsrScanRequest scanRequest;
8695 tANI_U8 *channelList = NULL, i;
8696 v_U32_t scanId = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308697 int status;
8698 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008699 v_U8_t* pP2pIe = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008700
Siddharth Bhal0c162d02014-05-06 19:50:42 +05308701#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8702 struct net_device *dev = NULL;
8703 if (NULL == request)
8704 {
8705 hddLog(VOS_TRACE_LEVEL_ERROR,
8706 "%s: scan req param null", __func__);
8707 return -EINVAL;
8708 }
8709 dev = request->wdev->netdev;
8710#endif
8711
8712 pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
8713 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8714 pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8715
Jeff Johnson295189b2012-06-20 16:38:30 -07008716 ENTER();
8717
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05308718
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05308719 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)",
8720 __func__, hdd_device_modetoString(pAdapter->device_mode),
8721 pAdapter->device_mode);
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05308722
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308723 status = wlan_hdd_validate_context(pHddCtx);
8724
8725 if (0 != status)
8726 {
8727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8728 "%s: HDD context is not valid", __func__);
8729 return status;
8730 }
8731
Siddharth Bhal0c162d02014-05-06 19:50:42 +05308732 if (NULL == pwextBuf)
8733 {
8734 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: invalid WEXT state\n",
8735 __func__);
8736 return -EIO;
8737 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05308738 cfg_param = pHddCtx->cfg_ini;
8739 pScanInfo = &pHddCtx->scan_info;
8740
Jeff Johnson295189b2012-06-20 16:38:30 -07008741#ifdef WLAN_BTAMP_FEATURE
8742 //Scan not supported when AMP traffic is on.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008743 if (VOS_TRUE == WLANBAP_AmpSessionOn())
Jeff Johnson295189b2012-06-20 16:38:30 -07008744 {
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08008745 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008746 "%s: No scanning when AMP is on", __func__);
8747 return -EOPNOTSUPP;
8748 }
8749#endif
8750 //Scan on any other interface is not supported.
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008751 if (pAdapter->device_mode == WLAN_HDD_SOFTAP)
Jeff Johnson295189b2012-06-20 16:38:30 -07008752 {
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008753 hddLog(VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05308754 "%s: Not scanning on device_mode = %s (%d)",
8755 __func__, hdd_device_modetoString(pAdapter->device_mode),
8756 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008757 return -EOPNOTSUPP;
8758 }
8759
8760 if (TRUE == pScanInfo->mScanPending)
8761 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05308762 if ( MAX_PENDING_LOG > pScanInfo->mScanPendingCounter++ )
8763 {
8764 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: mScanPending is TRUE", __func__);
8765 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008766 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07008767 }
8768
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308769 //Don't Allow Scan and return busy if Remain On
Jeff Johnson32d95a32012-09-10 13:15:23 -07008770 //Channel and action frame is pending
8771 //Otherwise Cancel Remain On Channel and allow Scan
8772 //If no action frame pending
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008773 if (0 != wlan_hdd_check_remain_on_channel(pAdapter))
Jeff Johnson32d95a32012-09-10 13:15:23 -07008774 {
Kiet Lamac06e2c2013-10-23 16:25:07 +05308775 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Remain On Channel Pending", __func__);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008776 return -EBUSY;
8777 }
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008778#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07008779 /* if tdls disagree scan right now, return immediately.
8780 tdls will schedule the scan when scan is allowed. (return SUCCESS)
8781 or will reject the scan if any TDLS is in progress. (return -EBUSY)
8782 */
8783 status = wlan_hdd_tdls_scan_callback (pAdapter,
8784 wiphy,
8785#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
8786 dev,
Gopichand Nakkalac3c42b92013-03-20 19:42:34 -07008787#endif
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07008788 request);
8789 if(status <= 0)
8790 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05308791 if(!status)
8792 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS in progress."
8793 "scan rejected %d", __func__, status);
8794 else
8795 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: TDLS teardown is ongoing %d",
8796 __func__, status);
8797
Gopichand Nakkala638ebc72013-03-21 18:04:02 -07008798 return status;
Gopichand Nakkala681989c2013-03-06 22:27:48 -08008799 }
8800#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -07008801
Jeff Johnson295189b2012-06-20 16:38:30 -07008802 if (mutex_lock_interruptible(&pHddCtx->tmInfo.tmOperationLock))
8803 {
8804 VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR,
Jeff Johnson1250df42012-12-10 14:31:52 -08008805 "%s: Acquire lock fail", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008806 return -EAGAIN;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308807 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008808 if (TRUE == pHddCtx->tmInfo.tmAction.enterImps)
8809 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05308810 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008811 "%s: MAX TM Level Scan not allowed", __func__);
8812 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308813 return -EBUSY;
Jeff Johnson295189b2012-06-20 16:38:30 -07008814 }
8815 mutex_unlock(&pHddCtx->tmInfo.tmOperationLock);
8816
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008817 /* Check if scan is allowed at this point of time.
8818 */
Rashmi Ramannab1429032014-04-26 14:59:09 +05308819 if (hdd_isConnectionInProgress(pHddCtx))
Madan Mohan Koyyalamudicfd53742013-01-11 15:29:03 -08008820 {
8821 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__);
8822 return -EBUSY;
8823 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05308824
Jeff Johnson295189b2012-06-20 16:38:30 -07008825 vos_mem_zero( &scanRequest, sizeof(scanRequest));
8826
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308827 hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d",
8828 (int)request->n_ssids);
8829
8830 /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1.
8831 * Becasue of this, driver is assuming that this is not wildcard scan and so
8832 * is not aging out the scan results.
8833 */
8834 if (request->ssids && '\0' == request->ssids->ssid[0])
Jeff Johnson295189b2012-06-20 16:38:30 -07008835 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308836 request->n_ssids = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008837 }
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308838
8839 if ((request->ssids) && (0 < request->n_ssids))
8840 {
8841 tCsrSSIDInfo *SsidInfo;
8842 int j;
8843 scanRequest.SSIDs.numOfSSIDs = request->n_ssids;
8844 /* Allocate num_ssid tCsrSSIDInfo structure */
8845 SsidInfo = scanRequest.SSIDs.SSIDList =
8846 ( tCsrSSIDInfo *)vos_mem_malloc(
8847 request->n_ssids*sizeof(tCsrSSIDInfo));
8848
8849 if(NULL == scanRequest.SSIDs.SSIDList)
8850 {
8851 hddLog(VOS_TRACE_LEVEL_ERROR,
8852 "%s: memory alloc failed SSIDInfo buffer", __func__);
8853 return -ENOMEM;
8854 }
8855
8856 /* copy all the ssid's and their length */
8857 for(j = 0; j < request->n_ssids; j++, SsidInfo++)
8858 {
8859 /* get the ssid length */
8860 SsidInfo->SSID.length = request->ssids[j].ssid_len;
8861 vos_mem_copy(SsidInfo->SSID.ssId, &request->ssids[j].ssid[0],
8862 SsidInfo->SSID.length);
8863 SsidInfo->SSID.ssId[SsidInfo->SSID.length] = '\0';
8864 hddLog(VOS_TRACE_LEVEL_INFO, "SSID number %d: %s",
8865 j, SsidInfo->SSID.ssId);
8866 }
8867 /* set the scan type to active */
8868 scanRequest.scanType = eSIR_ACTIVE_SCAN;
8869 }
8870 else if(WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07008871 {
Siddharth Bhal0c162d02014-05-06 19:50:42 +05308872 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
8873 TRACE_CODE_HDD_CFG80211_SCAN,
8874 pAdapter->sessionId, 0));
Jeff Johnson295189b2012-06-20 16:38:30 -07008875 /* set the scan type to active */
8876 scanRequest.scanType = eSIR_ACTIVE_SCAN;
Jeff Johnson295189b2012-06-20 16:38:30 -07008877 }
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308878 else
8879 {
8880 /*Set the scan type to default type, in this case it is ACTIVE*/
8881 scanRequest.scanType = pScanInfo->scan_mode;
8882 }
8883 scanRequest.minChnTime = cfg_param->nActiveMinChnTime;
8884 scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime;
Jeff Johnson295189b2012-06-20 16:38:30 -07008885
8886 /* set BSSType to default type */
8887 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
8888
8889 /*TODO: scan the requested channels only*/
8890
8891 /*Right now scanning all the channels */
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308892 if (MAX_CHANNEL < request->n_channels)
Jeff Johnson295189b2012-06-20 16:38:30 -07008893 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308894 hddLog(VOS_TRACE_LEVEL_WARN,
8895 "No of Scan Channels exceeded limit: %d", request->n_channels);
8896 request->n_channels = MAX_CHANNEL;
8897 }
8898
8899 hddLog(VOS_TRACE_LEVEL_INFO,
8900 "No of Scan Channels: %d", request->n_channels);
8901
8902
8903 if( request->n_channels )
8904 {
8905 char chList [(request->n_channels*5)+1];
8906 int len;
8907 channelList = vos_mem_malloc( request->n_channels );
8908 if( NULL == channelList )
c_hpothu53512302014-04-15 18:49:53 +05308909 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308910 hddLog(VOS_TRACE_LEVEL_ERROR,
8911 "%s: memory alloc failed channelList", __func__);
8912 status = -ENOMEM;
8913 goto free_mem;
c_hpothu53512302014-04-15 18:49:53 +05308914 }
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308915
8916 for( i = 0, len = 0; i < request->n_channels ; i++ )
8917 {
8918 channelList[i] = request->channels[i]->hw_value;
8919 len += snprintf(chList+len, 5, "%d ", channelList[i]);
8920 }
8921
Nirav Shah20ac06f2013-12-12 18:14:06 +05308922 hddLog(VOS_TRACE_LEVEL_INFO,
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308923 "Channel-List: %s ", chList);
8924 }
c_hpothu53512302014-04-15 18:49:53 +05308925
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308926 scanRequest.ChannelInfo.numOfChannels = request->n_channels;
8927 scanRequest.ChannelInfo.ChannelList = channelList;
8928
8929 /* set requestType to full scan */
8930 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
8931
8932 /* Flush the scan results(only p2p beacons) for STA scan and P2P
8933 * search (Flush on both full scan and social scan but not on single
8934 * channel scan).P2P search happens on 3 social channels (1, 6, 11)
8935 */
8936
8937 /* Supplicant does single channel scan after 8-way handshake
8938 * and in that case driver shoudnt flush scan results. If
8939 * driver flushes the scan results here and unfortunately if
8940 * the AP doesnt respond to our probe req then association
8941 * fails which is not desired
8942 */
8943
8944 if( request->n_channels != WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN )
8945 {
8946 hddLog(VOS_TRACE_LEVEL_DEBUG, "Flushing P2P Results");
8947 sme_ScanFlushP2PResult( WLAN_HDD_GET_HAL_CTX(pAdapter),
8948 pAdapter->sessionId );
8949 }
8950
8951 if( request->ie_len )
8952 {
8953 /* save this for future association (join requires this) */
8954 /*TODO: Array needs to be converted to dynamic allocation,
8955 * as multiple ie.s can be sent in cfg80211_scan_request structure
8956 * CR 597966
8957 */
8958 memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) );
8959 memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len);
8960 pScanInfo->scanAddIE.length = request->ie_len;
8961
8962 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8963 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
8964 (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07008965 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308966 if ( request->ie_len <= SIR_MAC_MAX_IE_LENGTH)
Jeff Johnson295189b2012-06-20 16:38:30 -07008967 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308968 pwextBuf->roamProfile.nAddIEScanLength = request->ie_len;
8969 memcpy( pwextBuf->roamProfile.addIEScan,
8970 request->ie, request->ie_len);
8971 }
8972 else
8973 {
8974 hddLog(VOS_TRACE_LEVEL_ERROR, "Scan Ie length is invalid:"
8975 "%zu", request->ie_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07008976 }
8977
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308978 }
8979 scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length;
8980 scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata;
8981
8982 pP2pIe = wlan_hdd_get_p2p_ie_ptr((v_U8_t*)request->ie,
8983 request->ie_len);
8984 if (pP2pIe != NULL)
8985 {
8986#ifdef WLAN_FEATURE_P2P_DEBUG
8987 if (((globalP2PConnectionStatus == P2P_GO_NEG_COMPLETED) ||
8988 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS)) &&
8989 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Nirav Shah20ac06f2013-12-12 18:14:06 +05308990 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308991 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_1;
8992 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
8993 "Go nego completed to Connection is started");
8994 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
8995 "for 8way Handshake");
Nirav Shah20ac06f2013-12-12 18:14:06 +05308996 }
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05308997 else if((globalP2PConnectionStatus == P2P_CLIENT_DISCONNECTED_STATE) &&
8998 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Jeff Johnson295189b2012-06-20 16:38:30 -07008999 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05309000 globalP2PConnectionStatus = P2P_CLIENT_CONNECTING_STATE_2;
9001 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P State] Changing state from "
9002 "Disconnected state to Connection is started");
9003 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P]P2P Scanning is started "
9004 "for 4way Handshake");
9005 }
9006#endif
9007
9008 /* no_cck will be set during p2p find to disable 11b rates */
9009 if(TRUE == request->no_cck)
9010 {
9011 hddLog(VOS_TRACE_LEVEL_INFO,
9012 "%s: This is a P2P Search", __func__);
9013 scanRequest.p2pSearch = 1;
9014
9015 if( request->n_channels == WLAN_HDD_P2P_SOCIAL_CHANNELS )
Agarwal Ashish4f616132013-12-30 23:32:50 +05309016 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05309017 /* set requestType to P2P Discovery */
9018 scanRequest.requestType = eCSR_SCAN_P2P_DISCOVERY;
9019 }
9020
9021 /*
9022 Skip Dfs Channel in case of P2P Search
9023 if it is set in ini file
9024 */
9025 if(cfg_param->skipDfsChnlInP2pSearch)
9026 {
9027 scanRequest.skipDfsChnlInP2pSearch = 1;
Agarwal Ashish4f616132013-12-30 23:32:50 +05309028 }
9029 else
9030 {
Padma, Santhosh Kumar787bd5c2014-05-15 20:09:31 +05309031 scanRequest.skipDfsChnlInP2pSearch = 0;
Agarwal Ashish4f616132013-12-30 23:32:50 +05309032 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009033
Agarwal Ashish4f616132013-12-30 23:32:50 +05309034 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009035 }
9036 }
9037
9038 INIT_COMPLETION(pScanInfo->scan_req_completion_event);
9039
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07009040 /* acquire the wakelock to avoid the apps suspend during the scan. To
9041 * address the following issues.
9042 * 1) Disconnected scenario: we are not allowing the suspend as WLAN is not in
9043 * BMPS/IMPS this result in android trying to suspend aggressively and backing off
9044 * for long time, this result in apps running at full power for long time.
9045 * 2) Connected scenario: If we allow the suspend during the scan, RIVA will
9046 * be stuck in full power because of resume BMPS
9047 */
9048 hdd_prevent_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07009049
Nirav Shah20ac06f2013-12-12 18:14:06 +05309050 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
9051 "requestType %d, scanType %d, minChnTime %d, maxChnTime %d,"
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05309052 "p2pSearch %d, skipDfsChnlInP2pSearch %d",
9053 scanRequest.requestType, scanRequest.scanType,
9054 scanRequest.minChnTime, scanRequest.maxChnTime,
Nirav Shah20ac06f2013-12-12 18:14:06 +05309055 scanRequest.p2pSearch, scanRequest.skipDfsChnlInP2pSearch);
9056
Jeff Johnsone7245742012-09-05 17:12:55 -07009057 status = sme_ScanRequest( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07009058 pAdapter->sessionId, &scanRequest, &scanId,
9059 &hdd_cfg80211_scan_done_callback, dev );
Jeff Johnsone7245742012-09-05 17:12:55 -07009060
Jeff Johnson295189b2012-06-20 16:38:30 -07009061 if (eHAL_STATUS_SUCCESS != status)
9062 {
9063 hddLog(VOS_TRACE_LEVEL_ERROR,
9064 "%s: sme_ScanRequest returned error %d", __func__, status);
9065 complete(&pScanInfo->scan_req_completion_event);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07009066 if(eHAL_STATUS_RESOURCES == status)
9067 {
Nirav Shah20ac06f2013-12-12 18:14:06 +05309068 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HO is in progress."
9069 "So defer the scan by informing busy",__func__);
Madan Mohan Koyyalamudi3b230fe2012-10-18 14:46:32 -07009070 status = -EBUSY;
9071 } else {
9072 status = -EIO;
9073 }
Madan Mohan Koyyalamudi9f5a10c2012-09-28 14:46:16 -07009074 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009075 goto free_mem;
9076 }
9077
9078 pScanInfo->mScanPending = TRUE;
9079 pAdapter->request = request;
9080 pScanInfo->scanId = scanId;
9081
9082 complete(&pScanInfo->scan_req_completion_event);
9083
9084free_mem:
9085 if( scanRequest.SSIDs.SSIDList )
9086 {
9087 vos_mem_free(scanRequest.SSIDs.SSIDList);
9088 }
9089
9090 if( channelList )
9091 vos_mem_free( channelList );
9092
9093 EXIT();
9094
9095 return status;
9096}
9097
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +05309098int wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
9099#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
9100 struct net_device *dev,
9101#endif
9102 struct cfg80211_scan_request *request)
9103{
9104 int ret;
9105
9106 vos_ssr_protect(__func__);
9107 ret = __wlan_hdd_cfg80211_scan(wiphy,
9108#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
9109 dev,
9110#endif
9111 request);
9112 vos_ssr_unprotect(__func__);
9113
9114 return ret;
9115}
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07009116
9117void hdd_select_cbmode( hdd_adapter_t *pAdapter,v_U8_t operationChannel)
9118{
9119 v_U8_t iniDot11Mode =
9120 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->dot11Mode;
9121 eHddDot11Mode hddDot11Mode = iniDot11Mode;
9122
Arun Kumar Khandavalli94a2bb02013-12-28 19:17:25 +05309123 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"),
9124 iniDot11Mode);
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07009125 switch ( iniDot11Mode )
9126 {
9127 case eHDD_DOT11_MODE_AUTO:
9128 case eHDD_DOT11_MODE_11ac:
9129 case eHDD_DOT11_MODE_11ac_ONLY:
9130#ifdef WLAN_FEATURE_11AC
9131 hddDot11Mode = eHDD_DOT11_MODE_11ac;
9132#else
9133 hddDot11Mode = eHDD_DOT11_MODE_11n;
9134#endif
9135 break;
9136 case eHDD_DOT11_MODE_11n:
9137 case eHDD_DOT11_MODE_11n_ONLY:
9138 hddDot11Mode = eHDD_DOT11_MODE_11n;
9139 break;
9140 default:
9141 hddDot11Mode = iniDot11Mode;
9142 break;
9143 }
9144 /* This call decides required channel bonding mode */
9145 sme_SelectCBMode((WLAN_HDD_GET_CTX(pAdapter)->hHal),
9146 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
9147 operationChannel);
9148}
9149
Jeff Johnson295189b2012-06-20 16:38:30 -07009150/*
9151 * FUNCTION: wlan_hdd_cfg80211_connect_start
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309152 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -07009153 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309154int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009155 const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel)
Jeff Johnson295189b2012-06-20 16:38:30 -07009156{
9157 int status = 0;
9158 hdd_wext_state_t *pWextState;
Yue Mae36e3552014-03-05 17:06:20 -08009159 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07009160 v_U32_t roamId;
9161 tCsrRoamProfile *pRoamProfile;
Jeff Johnson295189b2012-06-20 16:38:30 -07009162 eCsrAuthType RSNAuthType;
9163
9164 ENTER();
9165
9166 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Yue Mae36e3552014-03-05 17:06:20 -08009167 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9168
9169 status = wlan_hdd_validate_context(pHddCtx);
9170 if (status)
9171 {
9172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9173 "%s: HDD context is not valid!", __func__);
9174 return status;
9175 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309176
Jeff Johnson295189b2012-06-20 16:38:30 -07009177 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len)
9178 {
9179 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__);
9180 return -EINVAL;
9181 }
9182
9183 pRoamProfile = &pWextState->roamProfile;
9184
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309185 if (pRoamProfile)
Jeff Johnson295189b2012-06-20 16:38:30 -07009186 {
Jeff Johnsone7245742012-09-05 17:12:55 -07009187 hdd_station_ctx_t *pHddStaCtx;
9188 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009189
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309190 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnson295189b2012-06-20 16:38:30 -07009191 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode)
9192 {
9193 /*QoS not enabled in cfg file*/
9194 pRoamProfile->uapsd_mask = 0;
9195 }
9196 else
9197 {
9198 /*QoS enabled, update uapsd mask from cfg file*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309199 pRoamProfile->uapsd_mask =
Jeff Johnson295189b2012-06-20 16:38:30 -07009200 (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask;
9201 }
9202
9203 pRoamProfile->SSIDs.numOfSSIDs = 1;
9204 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
9205 vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309206 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Jeff Johnson295189b2012-06-20 16:38:30 -07009207 vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
9208 ssid, ssid_len);
9209
9210 if (bssid)
9211 {
9212 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
9213 vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid,
9214 WNI_CFG_BSSID_LEN);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309215 /* Save BSSID in seperate variable as well, as RoamProfile
9216 BSSID is getting zeroed out in the association process. And in
Jeff Johnson295189b2012-06-20 16:38:30 -07009217 case of join failure we should send valid BSSID to supplicant
9218 */
9219 vos_mem_copy((void *)(pWextState->req_bssId), bssid,
9220 WNI_CFG_BSSID_LEN);
9221 }
Dhanashri Atre51981c62013-06-13 11:47:57 -07009222 else
9223 {
9224 vos_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),WNI_CFG_BSSID_LEN);
9225 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009226
Arun Kumar Khandavalli94a2bb02013-12-28 19:17:25 +05309227 hddLog(LOG1, FL("Connect to SSID: %s opertating Channel: %u"),
9228 pRoamProfile->SSIDs.SSIDList->SSID.ssId, operatingChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -07009229 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
9230 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion))
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309231 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009232 /*set gen ie*/
9233 hdd_SetGENIEToCsr(pAdapter, &RSNAuthType);
9234 /*set auth*/
9235 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
9236 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009237#ifdef FEATURE_WLAN_WAPI
9238 if (pAdapter->wapi_info.nWapiMode)
9239 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009240 hddLog(LOG1, "%s: Setting WAPI AUTH Type and Encryption Mode values", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009241 switch (pAdapter->wapi_info.wapiAuthMode)
9242 {
9243 case WAPI_AUTH_MODE_PSK:
9244 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009245 hddLog(LOG1, "%s: WAPI AUTH TYPE: PSK: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07009246 pAdapter->wapi_info.wapiAuthMode);
9247 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_PSK;
9248 break;
9249 }
9250 case WAPI_AUTH_MODE_CERT:
9251 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009252 hddLog(LOG1, "%s: WAPI AUTH TYPE: CERT: %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07009253 pAdapter->wapi_info.wapiAuthMode);
9254 pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
9255 break;
9256 }
9257 } // End of switch
9258 if ( pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_PSK ||
9259 pAdapter->wapi_info.wapiAuthMode == WAPI_AUTH_MODE_CERT)
9260 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009261 hddLog(LOG1, "%s: WAPI PAIRWISE/GROUP ENCRYPTION: WPI", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009262 pRoamProfile->AuthType.numEntries = 1;
9263 pRoamProfile->EncryptionType.numEntries = 1;
9264 pRoamProfile->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
9265 pRoamProfile->mcEncryptionType.numEntries = 1;
9266 pRoamProfile->mcEncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
9267 }
9268 }
9269#endif /* FEATURE_WLAN_WAPI */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309270#ifdef WLAN_FEATURE_GTK_OFFLOAD
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309271 /* Initializing gtkOffloadReqParams */
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309272 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
9273 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
9274 {
Gopichand Nakkalad36ee622013-05-07 14:13:27 +05309275 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
9276 sizeof (tSirGtkOffloadParams));
9277 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +05309278 }
9279#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009280 pRoamProfile->csrPersona = pAdapter->device_mode;
9281
Jeff Johnson32d95a32012-09-10 13:15:23 -07009282 if( operatingChannel )
9283 {
9284 pRoamProfile->ChannelInfo.ChannelList = &operatingChannel;
9285 pRoamProfile->ChannelInfo.numOfChannels = 1;
9286 }
Chet Lanctot186b5732013-03-18 10:26:30 -07009287 else
9288 {
9289 pRoamProfile->ChannelInfo.ChannelList = NULL;
9290 pRoamProfile->ChannelInfo.numOfChannels = 0;
9291 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -07009292 if ( (WLAN_HDD_IBSS == pAdapter->device_mode) && operatingChannel)
9293 {
9294 hdd_select_cbmode(pAdapter,operatingChannel);
9295 }
Arun Kumar Khandavalli94a2bb02013-12-28 19:17:25 +05309296
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08009297 /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect()
9298 * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309299 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08009300 * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback()
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08009301 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
9302 */
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309303 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
9304 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
Abhishek Singhf4669da2014-05-26 15:07:49 +05309305 {
9306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9307 "%s: Set HDD connState to eConnectionState_Connecting",
9308 __func__);
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08009309 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
9310 eConnectionState_Connecting);
Abhishek Singhf4669da2014-05-26 15:07:49 +05309311 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309312 status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnson295189b2012-06-20 16:38:30 -07009313 pAdapter->sessionId, pRoamProfile, &roamId);
9314
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309315 if ((eHAL_STATUS_SUCCESS != status) &&
9316 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
9317 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode))
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05309318
9319 {
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08009320 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with "
9321 "status %d. -> NotConnected", __func__, pAdapter->sessionId, status);
9322 /* change back to NotAssociated */
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05309323 hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter),
Madan Mohan Koyyalamudi42dcd162012-12-03 16:34:04 -08009324 eConnectionState_NotConnected);
Madan Mohan Koyyalamudid5acbf52012-11-28 01:45:08 +05309325 }
Madan Mohan Koyyalamudidf86c422012-12-04 17:03:44 -08009326
9327 pRoamProfile->ChannelInfo.ChannelList = NULL;
9328 pRoamProfile->ChannelInfo.numOfChannels = 0;
9329
Jeff Johnson295189b2012-06-20 16:38:30 -07009330 }
9331 else
9332 {
9333 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid Roam profile", __func__);
9334 return -EINVAL;
9335 }
Madan Mohan Koyyalamudifd4e1da2012-11-09 17:50:19 -08009336 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07009337 return status;
9338}
9339
9340/*
9341 * FUNCTION: wlan_hdd_set_cfg80211_auth_type
9342 * This function is used to set the authentication type (OPEN/SHARED).
9343 *
9344 */
9345static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
9346 enum nl80211_auth_type auth_type)
9347{
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309348 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009349 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9350
9351 ENTER();
9352
9353 /*set authentication type*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309354 switch (auth_type)
Jeff Johnson295189b2012-06-20 16:38:30 -07009355 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009356 case NL80211_AUTHTYPE_AUTOMATIC:
Gopichand Nakkala29149562013-05-10 21:43:41 +05309357 hddLog(VOS_TRACE_LEVEL_INFO,
9358 "%s: set authentication type to AUTOSWITCH", __func__);
9359 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
9360 break;
9361
9362 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -07009363#ifdef WLAN_FEATURE_VOWIFI_11R
9364 case NL80211_AUTHTYPE_FT:
9365#endif /* WLAN_FEATURE_VOWIFI_11R */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309366 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07009367 "%s: set authentication type to OPEN", __func__);
9368 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
9369 break;
9370
9371 case NL80211_AUTHTYPE_SHARED_KEY:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309372 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07009373 "%s: set authentication type to SHARED", __func__);
9374 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
9375 break;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08009376#ifdef FEATURE_WLAN_ESE
Jeff Johnson295189b2012-06-20 16:38:30 -07009377 case NL80211_AUTHTYPE_NETWORK_EAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309378 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07009379 "%s: set authentication type to CCKM WPA", __func__);
9380 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required.
9381 break;
9382#endif
9383
9384
9385 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309386 hddLog(VOS_TRACE_LEVEL_ERROR,
9387 "%s: Unsupported authentication type %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07009388 auth_type);
9389 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
9390 return -EINVAL;
9391 }
9392
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309393 pWextState->roamProfile.AuthType.authType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07009394 pHddStaCtx->conn_info.authType;
9395 return 0;
9396}
9397
9398/*
9399 * FUNCTION: wlan_hdd_set_akm_suite
9400 * This function is used to set the key mgmt type(PSK/8021x).
9401 *
9402 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309403static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07009404 u32 key_mgmt
9405 )
9406{
9407 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9408 ENTER();
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309409
Jeff Johnson295189b2012-06-20 16:38:30 -07009410 /*set key mgmt type*/
9411 switch(key_mgmt)
9412 {
9413 case WLAN_AKM_SUITE_PSK:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05309414#ifdef WLAN_FEATURE_VOWIFI_11R
9415 case WLAN_AKM_SUITE_FT_PSK:
9416#endif
9417 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to PSK",
Jeff Johnson295189b2012-06-20 16:38:30 -07009418 __func__);
9419 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
9420 break;
9421
9422 case WLAN_AKM_SUITE_8021X:
Gopichand Nakkala356fb102013-03-06 12:34:04 +05309423#ifdef WLAN_FEATURE_VOWIFI_11R
9424 case WLAN_AKM_SUITE_FT_8021X:
9425#endif
9426 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to 8021x",
Jeff Johnson295189b2012-06-20 16:38:30 -07009427 __func__);
9428 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
9429 break;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08009430#ifdef FEATURE_WLAN_ESE
Jeff Johnson295189b2012-06-20 16:38:30 -07009431#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
9432#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
9433 case WLAN_AKM_SUITE_CCKM:
9434 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to CCKM",
9435 __func__);
9436 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
9437 break;
9438#endif
Leela Venkata Kiran Kumar Reddy Chiralae208a832014-04-27 22:34:25 -07009439#ifndef WLAN_AKM_SUITE_OSEN
9440#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
9441 case WLAN_AKM_SUITE_OSEN:
9442 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting key mgmt type to OSEN",
9443 __func__);
9444 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
9445 break;
9446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009447
9448 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309449 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07009450 __func__, key_mgmt);
9451 return -EINVAL;
9452
9453 }
9454 return 0;
9455}
9456
9457/*
9458 * FUNCTION: wlan_hdd_cfg80211_set_cipher
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309459 * This function is used to set the encryption type
Jeff Johnson295189b2012-06-20 16:38:30 -07009460 * (NONE/WEP40/WEP104/TKIP/CCMP).
9461 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309462static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter,
9463 u32 cipher,
Jeff Johnson295189b2012-06-20 16:38:30 -07009464 bool ucast
9465 )
9466{
9467 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309468 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009469 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9470
9471 ENTER();
9472
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309473 if (!cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07009474 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309475 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none",
Jeff Johnson295189b2012-06-20 16:38:30 -07009476 __func__, cipher);
9477 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9478 }
9479 else
9480 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309481
Jeff Johnson295189b2012-06-20 16:38:30 -07009482 /*set encryption method*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309483 switch (cipher)
Jeff Johnson295189b2012-06-20 16:38:30 -07009484 {
9485 case IW_AUTH_CIPHER_NONE:
9486 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9487 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309488
Jeff Johnson295189b2012-06-20 16:38:30 -07009489 case WLAN_CIPHER_SUITE_WEP40:
Gopichand Nakkala29149562013-05-10 21:43:41 +05309490 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson295189b2012-06-20 16:38:30 -07009491 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309492
Jeff Johnson295189b2012-06-20 16:38:30 -07009493 case WLAN_CIPHER_SUITE_WEP104:
Gopichand Nakkala29149562013-05-10 21:43:41 +05309494 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
Jeff Johnson295189b2012-06-20 16:38:30 -07009495 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309496
Jeff Johnson295189b2012-06-20 16:38:30 -07009497 case WLAN_CIPHER_SUITE_TKIP:
9498 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
9499 break;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309500
Jeff Johnson295189b2012-06-20 16:38:30 -07009501 case WLAN_CIPHER_SUITE_CCMP:
9502 encryptionType = eCSR_ENCRYPT_TYPE_AES;
9503 break;
9504#ifdef FEATURE_WLAN_WAPI
9505 case WLAN_CIPHER_SUITE_SMS4:
9506 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
9507 break;
9508#endif
9509
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08009510#ifdef FEATURE_WLAN_ESE
Jeff Johnson295189b2012-06-20 16:38:30 -07009511 case WLAN_CIPHER_SUITE_KRK:
9512 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
9513 break;
9514#endif
9515 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309516 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07009517 __func__, cipher);
9518 return -EOPNOTSUPP;
9519 }
9520 }
9521
9522 if (ucast)
9523 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309524 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07009525 __func__, encryptionType);
9526 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
9527 pWextState->roamProfile.EncryptionType.numEntries = 1;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309528 pWextState->roamProfile.EncryptionType.encryptionType[0] =
Jeff Johnson295189b2012-06-20 16:38:30 -07009529 encryptionType;
9530 }
9531 else
9532 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309533 hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07009534 __func__, encryptionType);
9535 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
9536 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
9537 pWextState->roamProfile.mcEncryptionType.encryptionType[0] = encryptionType;
9538 }
9539
9540 return 0;
9541}
9542
9543
9544/*
9545 * FUNCTION: wlan_hdd_cfg80211_set_ie
9546 * This function is used to parse WPA/RSN IE's.
9547 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309548int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter,
9549 u8 *ie,
Jeff Johnson295189b2012-06-20 16:38:30 -07009550 size_t ie_len
9551 )
9552{
9553 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9554 u8 *genie = ie;
9555 v_U16_t remLen = ie_len;
9556#ifdef FEATURE_WLAN_WAPI
9557 v_U32_t akmsuite[MAX_NUM_AKM_SUITES];
9558 u16 *tmp;
9559 v_U16_t akmsuiteCount;
9560 int *akmlist;
9561#endif
9562 ENTER();
9563
9564 /* clear previous assocAddIE */
9565 pWextState->assocAddIE.length = 0;
9566 pWextState->roamProfile.bWPSAssociation = VOS_FALSE;
Leela Venkata Kiran Kumar Reddy Chiralaf257bef2014-04-11 18:48:12 -07009567 pWextState->roamProfile.bOSENAssociation = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009568
9569 while (remLen >= 2)
9570 {
9571 v_U16_t eLen = 0;
9572 v_U8_t elementId;
9573 elementId = *genie++;
9574 eLen = *genie++;
9575 remLen -= 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309576
Arif Hussain6d2a3322013-11-17 19:50:10 -08009577 hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07009578 __func__, elementId, eLen);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309579
9580 switch ( elementId )
Jeff Johnson295189b2012-06-20 16:38:30 -07009581 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309582 case DOT11F_EID_WPA:
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009583 if (4 > eLen) /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
Jeff Johnson295189b2012-06-20 16:38:30 -07009584 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309585 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07009586 "%s: Invalid WPA IE", __func__);
9587 return -EINVAL;
9588 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309589 else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4))
Jeff Johnson295189b2012-06-20 16:38:30 -07009590 {
9591 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309592 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07009593 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309594
Jeff Johnson295189b2012-06-20 16:38:30 -07009595 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
9596 {
Jeff Johnson902c9832012-12-10 14:28:09 -08009597 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. "
9598 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07009599 VOS_ASSERT(0);
9600 return -ENOMEM;
9601 }
9602 // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
9603 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
9604 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309605
Jeff Johnson295189b2012-06-20 16:38:30 -07009606 pWextState->roamProfile.bWPSAssociation = VOS_TRUE;
9607 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
9608 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
9609 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309610 else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3))
9611 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009612 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2);
9613 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
9614 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/);
9615 pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE;
9616 pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len;
9617 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309618 else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE,
Kiet Lam8da98992013-11-21 15:59:07 +05309619 P2P_OUI_TYPE_SIZE)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009620 {
9621 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309622 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07009623 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309624
Jeff Johnson295189b2012-06-20 16:38:30 -07009625 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
9626 {
Jeff Johnson902c9832012-12-10 14:28:09 -08009627 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
9628 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07009629 VOS_ASSERT(0);
9630 return -ENOMEM;
9631 }
9632 // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE
9633 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
9634 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309635
Jeff Johnson295189b2012-06-20 16:38:30 -07009636 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
9637 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
9638 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009639#ifdef WLAN_FEATURE_WFD
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309640 else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE,
9641 WFD_OUI_TYPE_SIZE))
Jeff Johnson295189b2012-06-20 16:38:30 -07009642 /*Consider WFD IE, only for P2P Client */
9643 && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9644 {
9645 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309646 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)",
Jeff Johnson295189b2012-06-20 16:38:30 -07009647 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309648
Jeff Johnson295189b2012-06-20 16:38:30 -07009649 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
9650 {
Jeff Johnson902c9832012-12-10 14:28:09 -08009651 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
9652 "Need bigger buffer space");
Jeff Johnson295189b2012-06-20 16:38:30 -07009653 VOS_ASSERT(0);
9654 return -ENOMEM;
9655 }
9656 // WFD IE is saved to Additional IE ; it should be accumulated to handle
9657 // WPS IE + P2P IE + WFD IE
9658 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
9659 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309660
Jeff Johnson295189b2012-06-20 16:38:30 -07009661 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
9662 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
9663 }
9664#endif
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009665 /* Appending HS 2.0 Indication Element in Assiciation Request */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309666 else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE,
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07009667 HS20_OUI_TYPE_SIZE)) )
9668 {
9669 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309670 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)",
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07009671 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009672
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07009673 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
9674 {
Jeff Johnson902c9832012-12-10 14:28:09 -08009675 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
9676 "Need bigger buffer space");
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07009677 VOS_ASSERT(0);
9678 return -ENOMEM;
9679 }
9680 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
9681 pWextState->assocAddIE.length += eLen + 2;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009682
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07009683 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
9684 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
9685 }
Leela Venkata Kiran Kumar Reddy Chiralaf257bef2014-04-11 18:48:12 -07009686 /* Appending OSEN Information Element in Assiciation Request */
9687 else if ( (0 == memcmp(&genie[0], OSEN_OUI_TYPE,
9688 OSEN_OUI_TYPE_SIZE)) )
9689 {
9690 v_U16_t curAddIELen = pWextState->assocAddIE.length;
9691 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OSEN IE(len %d)",
9692 __func__, eLen + 2);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009693
Leela Venkata Kiran Kumar Reddy Chiralaf257bef2014-04-11 18:48:12 -07009694 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
9695 {
9696 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
9697 "Need bigger buffer space");
9698 VOS_ASSERT(0);
9699 return -ENOMEM;
9700 }
9701 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
9702 pWextState->assocAddIE.length += eLen + 2;
9703
9704 pWextState->roamProfile.bOSENAssociation = VOS_TRUE;
9705 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
9706 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
9707 }
9708
9709 break;
Praveen Kumar Sirisilla7d68b7b2013-09-22 14:01:42 -07009710 if (WLAN_HDD_IBSS == pAdapter->device_mode) {
9711
9712 /* populating as ADDIE in beacon frames */
9713 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
9714 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, genie - 2, eLen + 2,
9715 NULL, eANI_BOOLEAN_FALSE)== eHAL_STATUS_SUCCESS)
9716 {
9717 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
9718 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
9719 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
9720 {
9721 hddLog(LOGE,
9722 "Coldn't pass "
9723 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG to CCM");
9724 }
9725 }/* ccmCfgSetStr(,WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, , )*/
9726 else
9727 hddLog(LOGE,
9728 "Could not pass on "
9729 "WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA to CCM");
9730
9731 /* IBSS mode doesn't contain params->proberesp_ies still
9732 beaconIE's need to be populated in probe response frames */
9733 if ( (NULL != (genie - 2)) && (0 != eLen + 2) )
9734 {
9735 u16 rem_probe_resp_ie_len = eLen + 2;
9736 u8 probe_rsp_ie_len[3] = {0};
9737 u8 counter = 0;
9738
9739 /* Check Probe Resp Length if it is greater then 255 then
9740 Store Probe Rsp IEs into WNI_CFG_PROBE_RSP_ADDNIE_DATA1
9741 & WNI_CFG_PROBE_RSP_ADDNIE_DATA2 CFG Variable As We are
9742 not able Store More then 255 bytes into One Variable */
9743
9744 while ((rem_probe_resp_ie_len > 0) && (counter < 3))
9745 {
9746 if (rem_probe_resp_ie_len > MAX_CFG_STRING_LEN)
9747 {
9748 probe_rsp_ie_len[counter++] = MAX_CFG_STRING_LEN;
9749 rem_probe_resp_ie_len -= MAX_CFG_STRING_LEN;
9750 }
9751 else
9752 {
9753 probe_rsp_ie_len[counter++] = rem_probe_resp_ie_len;
9754 rem_probe_resp_ie_len = 0;
9755 }
9756 }
9757
9758 rem_probe_resp_ie_len = 0;
9759
9760 if (probe_rsp_ie_len[0] > 0)
9761 {
9762 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
9763 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
9764 (tANI_U8*)(genie - 2),
9765 probe_rsp_ie_len[0], NULL,
9766 eANI_BOOLEAN_FALSE)
9767 == eHAL_STATUS_FAILURE)
9768 {
9769 hddLog(LOGE,
9770 "Could not pass"
9771 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
9772 }
9773 rem_probe_resp_ie_len += probe_rsp_ie_len[0];
9774 }
9775
9776 if (probe_rsp_ie_len[1] > 0)
9777 {
9778 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
9779 WNI_CFG_PROBE_RSP_ADDNIE_DATA2,
9780 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
9781 probe_rsp_ie_len[1], NULL,
9782 eANI_BOOLEAN_FALSE)
9783 == eHAL_STATUS_FAILURE)
9784 {
9785 hddLog(LOGE,
9786 "Could not pass"
9787 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
9788 }
9789 rem_probe_resp_ie_len += probe_rsp_ie_len[1];
9790 }
9791
9792 if (probe_rsp_ie_len[2] > 0)
9793 {
9794 if (ccmCfgSetStr(WLAN_HDD_GET_HAL_CTX(pAdapter),
9795 WNI_CFG_PROBE_RSP_ADDNIE_DATA3,
9796 (tANI_U8*)(genie - (2 + rem_probe_resp_ie_len)),
9797 probe_rsp_ie_len[2], NULL,
9798 eANI_BOOLEAN_FALSE)
9799 == eHAL_STATUS_FAILURE)
9800 {
9801 hddLog(LOGE,
9802 "Could not pass"
9803 "on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
9804 }
9805 rem_probe_resp_ie_len += probe_rsp_ie_len[2];
9806 }
9807
9808 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
9809 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
9810 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
9811 {
9812 hddLog(LOGE,
9813 "Could not pass"
9814 "on WNI_CFG_PROBE_RSP_ADDNIE_FLAG to CCM");
9815 }
9816 }
9817 else
9818 {
9819 // Reset WNI_CFG_PROBE_RSP Flags
9820 wlan_hdd_reset_prob_rspies(pAdapter);
9821
9822 hddLog(VOS_TRACE_LEVEL_INFO,
9823 "%s: No Probe Response IE received in set beacon",
9824 __func__);
9825 }
9826 } /* end of if (WLAN_HDD_IBSS == pAdapter->device_mode) */
Jeff Johnson295189b2012-06-20 16:38:30 -07009827 break;
9828 case DOT11F_EID_RSN:
9829 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set RSN IE(len %d)",__func__, eLen + 2);
9830 memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN );
9831 memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)/*ie_len*/);
9832 pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE;
9833 pWextState->roamProfile.nRSNReqIELength = eLen + 2; //ie_len;
9834 break;
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009835 /* Appending Extended Capabilities with Interworking bit set in Assoc Req */
9836 case DOT11F_EID_EXTCAP:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309837 {
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009838 v_U16_t curAddIELen = pWextState->assocAddIE.length;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309839 hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)",
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009840 __func__, eLen + 2);
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309841
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009842 if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) )
9843 {
Jeff Johnson902c9832012-12-10 14:28:09 -08009844 hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE "
9845 "Need bigger buffer space");
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009846 VOS_ASSERT(0);
9847 return -ENOMEM;
9848 }
9849 memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2);
9850 pWextState->assocAddIE.length += eLen + 2;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309851
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009852 pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata;
9853 pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length;
9854 break;
9855 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009856#ifdef FEATURE_WLAN_WAPI
9857 case WLAN_EID_WAPI:
9858 pAdapter->wapi_info.nWapiMode = 1; //Setting WAPI Mode to ON=1
Jeff Johnson0299d0a2013-10-30 12:37:43 -07009859 hddLog(VOS_TRACE_LEVEL_INFO, "WAPI MODE IS %u",
Jeff Johnson295189b2012-06-20 16:38:30 -07009860 pAdapter->wapi_info.nWapiMode);
9861 tmp = (u16 *)ie;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309862 tmp = tmp + 2; // Skip element Id and Len, Version
Jeff Johnson295189b2012-06-20 16:38:30 -07009863 akmsuiteCount = WPA_GET_LE16(tmp);
9864 tmp = tmp + 1;
9865 akmlist = (int *)(tmp);
9866 if(akmsuiteCount <= MAX_NUM_AKM_SUITES)
9867 {
9868 memcpy(akmsuite, akmlist, (4*akmsuiteCount));
9869 }
9870 else
9871 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08009872 hddLog(VOS_TRACE_LEVEL_FATAL, "Invalid akmSuite count");
Jeff Johnson295189b2012-06-20 16:38:30 -07009873 VOS_ASSERT(0);
9874 return -EINVAL;
9875 }
9876
9877 if (WAPI_PSK_AKM_SUITE == akmsuite[0])
9878 {
9879 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009880 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009881 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009883 if (WAPI_CERT_AKM_SUITE == akmsuite[0])
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309884 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009885 hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009886 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009887 pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT;
9888 }
9889 break;
9890#endif
9891 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309892 hddLog (VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07009893 "%s Set UNKNOWN IE %X", __func__, elementId);
Madan Mohan Koyyalamudief3b66e2012-10-11 14:29:42 -07009894 /* when Unknown IE is received we should break and continue
9895 * to the next IE in the buffer instead we were returning
9896 * so changing this to break */
9897 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009898 }
9899 genie += eLen;
9900 remLen -= eLen;
9901 }
9902 EXIT();
9903 return 0;
9904}
9905
9906/*
Gopichand Nakkala18f0c262013-05-07 23:25:08 +05309907 * FUNCTION: hdd_isWPAIEPresent
9908 * Parse the received IE to find the WPA IE
9909 *
9910 */
9911static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len)
9912{
9913 v_U8_t eLen = 0;
9914 v_U16_t remLen = ie_len;
9915 v_U8_t elementId = 0;
9916
9917 while (remLen >= 2)
9918 {
9919 elementId = *ie++;
9920 eLen = *ie++;
9921 remLen -= 2;
9922 if (eLen > remLen)
9923 {
9924 hddLog(VOS_TRACE_LEVEL_ERROR,
9925 "%s: IE length is wrong %d", __func__, eLen);
9926 return FALSE;
9927 }
9928 if ((elementId == DOT11F_EID_WPA) && (remLen > 5))
9929 {
9930 /* OUI - 0x00 0X50 0XF2
9931 WPA Information Element - 0x01
9932 WPA version - 0x01*/
9933 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
9934 return TRUE;
9935 }
9936 ie += eLen;
9937 remLen -= eLen;
9938 }
9939 return FALSE;
9940}
9941
9942/*
Jeff Johnson295189b2012-06-20 16:38:30 -07009943 * FUNCTION: wlan_hdd_cfg80211_set_privacy
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309944 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -07009945 * parameters during connect operation.
9946 */
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309947int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -07009948 struct cfg80211_connect_params *req
9949 )
9950{
9951 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309952 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009953 ENTER();
9954
9955 /*set wpa version*/
9956 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
9957
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309958 if (req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07009959 {
Gopichand Nakkala781ded42013-06-28 12:10:45 +05309960 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions)
Jeff Johnson295189b2012-06-20 16:38:30 -07009961 {
9962 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
9963 }
9964 else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions)
9965 {
9966 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9967 }
9968 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309969
9970 hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -07009971 pWextState->wpaVersion);
9972
9973 /*set authentication type*/
9974 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
9975
9976 if (0 > status)
9977 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309978 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07009979 "%s: failed to set authentication type ", __func__);
9980 return status;
9981 }
9982
9983 /*set key mgmt type*/
9984 if (req->crypto.n_akm_suites)
9985 {
9986 status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
9987 if (0 > status)
9988 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +05309989 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite",
Jeff Johnson295189b2012-06-20 16:38:30 -07009990 __func__);
9991 return status;
9992 }
9993 }
9994
9995 /*set pairwise cipher type*/
9996 if (req->crypto.n_ciphers_pairwise)
9997 {
9998 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
9999 req->crypto.ciphers_pairwise[0], true);
10000 if (0 > status)
10001 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010002 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070010003 "%s: failed to set unicast cipher type", __func__);
10004 return status;
10005 }
10006 }
10007 else
10008 {
10009 /*Reset previous cipher suite to none*/
10010 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
10011 if (0 > status)
10012 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010013 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070010014 "%s: failed to set unicast cipher type", __func__);
10015 return status;
10016 }
10017 }
10018
10019 /*set group cipher type*/
10020 status = wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
10021 false);
10022
10023 if (0 > status)
10024 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010025 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type",
Jeff Johnson295189b2012-06-20 16:38:30 -070010026 __func__);
10027 return status;
10028 }
10029
Chet Lanctot186b5732013-03-18 10:26:30 -070010030#ifdef WLAN_FEATURE_11W
10031 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
10032#endif
10033
Jeff Johnson295189b2012-06-20 16:38:30 -070010034 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/
10035 if (req->ie_len)
10036 {
10037 status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
10038 if ( 0 > status)
10039 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010040 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -070010041 __func__);
10042 return status;
10043 }
10044 }
10045
10046 /*incase of WEP set default key information*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010047 if (req->key && req->key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -070010048 {
10049 if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
10050 || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0])
10051 )
10052 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010053 if ( IW_AUTH_KEY_MGMT_802_1X
Jeff Johnson295189b2012-06-20 16:38:30 -070010054 == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X ))
10055 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010056 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -070010057 __func__);
10058 return -EOPNOTSUPP;
10059 }
10060 else
10061 {
10062 u8 key_len = req->key_len;
10063 u8 key_idx = req->key_idx;
10064
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010065 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
Jeff Johnson295189b2012-06-20 16:38:30 -070010066 && (CSR_MAX_NUM_KEY > key_idx)
10067 )
10068 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010069 hddLog(VOS_TRACE_LEVEL_INFO,
10070 "%s: setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010071 __func__, key_idx, key_len);
10072 vos_mem_copy(
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010073 &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0],
Jeff Johnson295189b2012-06-20 16:38:30 -070010074 req->key, key_len);
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010075 pWextState->roamProfile.Keys.KeyLength[key_idx] =
Jeff Johnson295189b2012-06-20 16:38:30 -070010076 (u8)key_len;
10077 pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx;
10078 }
10079 }
10080 }
10081 }
10082
10083 return status;
10084}
10085
10086/*
Vinay Krishna Eranna21042322014-01-08 19:21:39 +053010087 * FUNCTION: wlan_hdd_try_disconnect
10088 * This function is used to disconnect from previous
10089 * connection
10090 */
10091static int wlan_hdd_try_disconnect( hdd_adapter_t *pAdapter )
10092{
10093 long ret = 0;
10094 hdd_station_ctx_t *pHddStaCtx;
10095 eMib_dot11DesiredBssType connectedBssType;
10096
10097 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10098
10099 hdd_connGetConnectedBssType(pHddStaCtx,&connectedBssType );
10100
10101 if((eMib_dot11DesiredBssType_independent == connectedBssType) ||
10102 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
10103 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState))
10104 {
10105 /* Issue disconnect to CSR */
10106 INIT_COMPLETION(pAdapter->disconnect_comp_var);
10107 if( eHAL_STATUS_SUCCESS ==
10108 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
10109 pAdapter->sessionId,
10110 eCSR_DISCONNECT_REASON_UNSPECIFIED ) )
10111 {
10112 ret = wait_for_completion_interruptible_timeout(
10113 &pAdapter->disconnect_comp_var,
10114 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
10115 if (0 >= ret)
10116 {
10117 hddLog(LOGE, FL("Failed to receive disconnect event"));
10118 return -EALREADY;
10119 }
10120 }
10121 }
10122 else if(eConnectionState_Disconnecting == pHddStaCtx->conn_info.connState)
10123 {
10124 ret = wait_for_completion_interruptible_timeout(
10125 &pAdapter->disconnect_comp_var,
10126 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
10127 if (0 >= ret)
10128 {
10129 hddLog(LOGE, FL("Failed to receive disconnect event"));
10130 return -EALREADY;
10131 }
10132 }
10133
10134 return 0;
10135}
10136
10137/*
Agarwal Ashish51325b52014-06-16 16:50:49 +053010138 * FUNCTION: __wlan_hdd_cfg80211_connect
10139 * This function is used to start the association process
Jeff Johnson295189b2012-06-20 16:38:30 -070010140 */
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +053010141static int __wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -070010142 struct net_device *ndev,
10143 struct cfg80211_connect_params *req
10144 )
10145{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010146 int status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010147 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev );
Sushant Kaushikba6764e2014-06-30 19:52:09 +053010148 hdd_adapter_t *pHostapdAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010149 VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL;
Sushant Kaushikba6764e2014-06-30 19:52:09 +053010150 hdd_context_t *pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010151
10152 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010153
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053010154 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10155 TRACE_CODE_HDD_CFG80211_CONNECT,
10156 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010157 hddLog(VOS_TRACE_LEVEL_INFO,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +053010158 "%s: device_mode = %s (%d)", __func__,
10159 hdd_device_modetoString(pAdapter->device_mode),
10160 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -070010161
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010162 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Rajesh Chauhana0516c62014-01-30 16:11:18 -080010163 if (!pHddCtx)
10164 {
10165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10166 "%s: HDD context is null", __func__);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010167 return -EINVAL;
Rajesh Chauhana0516c62014-01-30 16:11:18 -080010168 }
10169
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010170 status = wlan_hdd_validate_context(pHddCtx);
10171
10172 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -070010173 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10175 "%s: HDD context is not valid", __func__);
10176 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -070010177 }
10178
Agarwal Ashish51325b52014-06-16 16:50:49 +053010179 if (vos_max_concurrent_connections_reached()) {
10180 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
10181 return -ECONNREFUSED;
10182 }
10183
Jeff Johnson295189b2012-06-20 16:38:30 -070010184#ifdef WLAN_BTAMP_FEATURE
10185 //Infra connect not supported when AMP traffic is on.
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010186 if( VOS_TRUE == WLANBAP_AmpSessionOn() )
Jeff Johnson295189b2012-06-20 16:38:30 -070010187 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010188 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070010189 "%s: No connection when AMP is on", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080010190 return -ECONNREFUSED;
Jeff Johnson295189b2012-06-20 16:38:30 -070010191 }
10192#endif
Vinay Krishna Eranna21042322014-01-08 19:21:39 +053010193
10194 //If Device Mode is Station Concurrent Sessions Exit BMps
10195 //P2P Mode will be taken care in Open/close adapter
10196 if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
Agarwal Ashish51325b52014-06-16 16:50:49 +053010197 (vos_concurrent_open_sessions_running())) {
10198 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx,
10199 WLAN_HDD_INFRA_STATION);
Vinay Krishna Eranna21042322014-01-08 19:21:39 +053010200 }
10201
10202 /*Try disconnecting if already in connected state*/
10203 status = wlan_hdd_try_disconnect(pAdapter);
10204 if ( 0 > status)
10205 {
10206 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
10207 " connection"));
10208 return -EALREADY;
10209 }
10210
Jeff Johnson295189b2012-06-20 16:38:30 -070010211 /*initialise security parameters*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010212 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
Jeff Johnson295189b2012-06-20 16:38:30 -070010213
10214 if ( 0 > status)
10215 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010216 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params",
Jeff Johnson295189b2012-06-20 16:38:30 -070010217 __func__);
10218 return status;
10219 }
Sushant Kaushikba6764e2014-06-30 19:52:09 +053010220 /* For SAP + STA concurrency , driver only supports SCC.
10221 * if SAP is ON, driver will stop it and after assoc completion,
10222 * or failure, SAP will be started on STA channel to force SCC.
10223 */
10224 pHostapdAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP);
10225 if (pHostapdAdapter != NULL)
10226 {
10227 hddLog(VOS_TRACE_LEVEL_INFO, "Close SAP until STA is connected");
10228 if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags))
10229 {
10230 WLANSAP_StopBss((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext);
10231 clear_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags);
10232 }
10233 }
Mohit Khanna765234a2012-09-11 15:08:35 -070010234 if ( req->channel )
10235 {
10236 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
10237 req->ssid_len, req->bssid,
10238 req->channel->hw_value);
10239 }
10240 else
10241 {
10242 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010243 req->ssid_len, req->bssid, 0);
Mohit Khanna765234a2012-09-11 15:08:35 -070010244 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010245
10246 if (0 > status)
10247 {
10248 //ReEnable BMPS if disabled
10249 if((VOS_STATUS_SUCCESS == exitbmpsStatus) &&
10250 (NULL != pHddCtx))
10251 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053010252 if (pHddCtx->hdd_wlan_suspended)
10253 {
10254 hdd_set_pwrparams(pHddCtx);
10255 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010256 //ReEnable Bmps and Imps back
10257 hdd_enable_bmps_imps(pHddCtx);
10258 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010259 hddLog(VOS_TRACE_LEVEL_ERROR, FL("connect failed"));
Jeff Johnson295189b2012-06-20 16:38:30 -070010260 return status;
10261 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010262 pHddCtx->isAmpAllowed = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010263 EXIT();
10264 return status;
10265}
10266
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +053010267static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy,
10268 struct net_device *ndev,
10269 struct cfg80211_connect_params *req)
10270{
10271 int ret;
10272 vos_ssr_protect(__func__);
10273 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
10274 vos_ssr_unprotect(__func__);
10275
10276 return ret;
10277}
Jeff Johnson295189b2012-06-20 16:38:30 -070010278
10279/*
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010280 * FUNCTION: wlan_hdd_disconnect
10281 * This function is used to issue a disconnect request to SME
10282 */
10283int wlan_hdd_disconnect( hdd_adapter_t *pAdapter, u16 reason )
10284{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010285 int status;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010286 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010287 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010288 long ret;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010289
10290 status = wlan_hdd_validate_context(pHddCtx);
10291
10292 if (0 != status)
10293 {
10294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10295 "%s: HDD context is not valid", __func__);
10296 return status;
10297 }
10298
10299 pHddCtx->isAmpAllowed = VOS_TRUE;
Abhishek Singhf4669da2014-05-26 15:07:49 +053010300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10301 "%s: Set HDD connState to eConnectionState_Disconnecting",
10302 __func__);
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +053010303 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010304 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010305
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010306 /*issue disconnect*/
Arun Kumar Khandavalli94a2bb02013-12-28 19:17:25 +053010307
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010308 status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter),
10309 pAdapter->sessionId, reason);
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010310 if(eHAL_STATUS_CMD_NOT_QUEUED == status)
10311 {
10312 hddLog(VOS_TRACE_LEVEL_INFO,
10313 FL("status = %d, already disconnected"),
10314 (int)status );
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010315
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010316 }
10317 else if ( 0 != status )
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010318 {
10319 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -080010320 "%s csrRoamDisconnect failure, returned %d",
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010321 __func__, (int)status );
10322 return -EINVAL;
10323 }
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010324 ret = wait_for_completion_interruptible_timeout(
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010325 &pAdapter->disconnect_comp_var,
10326 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010327 if (!ret && ( eHAL_STATUS_CMD_NOT_QUEUED != status ))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010328 {
10329 hddLog(VOS_TRACE_LEVEL_ERROR,
Mahesh A Saptasagar05a357e2014-02-26 16:28:06 +053010330 "%s: Failed to disconnect, timed out", __func__);
10331 return -ETIMEDOUT;
10332 }
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010333 else if (ret == -ERESTARTSYS)
Mahesh A Saptasagar05a357e2014-02-26 16:28:06 +053010334 {
10335 hddLog(VOS_TRACE_LEVEL_ERROR,
10336 "%s: Failed to disconnect, wait interrupted", __func__);
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010337 return ret;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010338 }
Abhishek Singhdc2bfd42014-06-19 17:59:05 +053010339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10340 FL("Set HDD connState to eConnectionState_NotConnected"));
10341 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
10342
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010343 /*stop tx queues*/
10344 netif_tx_disable(pAdapter->dev);
10345 netif_carrier_off(pAdapter->dev);
Mahesh A Saptasagar05a357e2014-02-26 16:28:06 +053010346 return 0;
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010347}
10348
10349
10350/*
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +053010351 * FUNCTION: __wlan_hdd_cfg80211_disconnect
Jeff Johnson295189b2012-06-20 16:38:30 -070010352 * This function is used to issue a disconnect request to SME
10353 */
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +053010354static int __wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -070010355 struct net_device *dev,
10356 u16 reason
10357 )
10358{
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010359 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010360 tCsrRoamProfile *pRoamProfile =
10361 &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010362 int status;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010363 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10364 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +053010365#ifdef FEATURE_WLAN_TDLS
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -080010366 tANI_U8 staIdx;
10367#endif
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010368
Jeff Johnson295189b2012-06-20 16:38:30 -070010369 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010370
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053010371 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10372 TRACE_CODE_HDD_CFG80211_DISCONNECT,
10373 pAdapter->sessionId, reason));
Sushant Kaushik8bc7df22014-04-09 17:55:29 +053010374 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s(%d)",
10375 __func__, hdd_device_modetoString(pAdapter->device_mode),
10376 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -070010377
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010378 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d",
10379 __func__, reason);
Jeff Johnson295189b2012-06-20 16:38:30 -070010380
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010381 status = wlan_hdd_validate_context(pHddCtx);
10382
10383 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -070010384 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10386 "%s: HDD context is not valid", __func__);
10387 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -070010388 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010389
Jeff Johnson295189b2012-06-20 16:38:30 -070010390 if (NULL != pRoamProfile)
10391 {
10392 /*issue disconnect request to SME, if station is in connected state*/
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +053010393 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
10394 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting))
Jeff Johnson295189b2012-06-20 16:38:30 -070010395 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010396 eCsrRoamDisconnectReason reasonCode =
Jeff Johnson295189b2012-06-20 16:38:30 -070010397 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Gopichand Nakkalaaa353782013-05-17 20:36:22 +053010398 hdd_scaninfo_t *pScanInfo;
Jeff Johnson295189b2012-06-20 16:38:30 -070010399 switch(reason)
10400 {
10401 case WLAN_REASON_MIC_FAILURE:
10402 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
10403 break;
10404
10405 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
10406 case WLAN_REASON_DISASSOC_AP_BUSY:
10407 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
10408 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
10409 break;
10410
10411 case WLAN_REASON_PREV_AUTH_NOT_VALID:
10412 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
Abhishek Singhc3269a52014-05-21 17:22:24 +053010413 case WLAN_REASON_DEAUTH_LEAVING:
Jeff Johnson295189b2012-06-20 16:38:30 -070010414 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
10415 break;
10416
Jeff Johnson295189b2012-06-20 16:38:30 -070010417 default:
10418 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
10419 break;
10420 }
Gopichand Nakkalaaa353782013-05-17 20:36:22 +053010421 pScanInfo = &pHddCtx->scan_info;
10422 if (pScanInfo->mScanPending)
10423 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +053010424 hddLog(VOS_TRACE_LEVEL_INFO, "Disconnect is in progress, "
Gopichand Nakkalaaa353782013-05-17 20:36:22 +053010425 "Aborting Scan");
Srinivas, Dasari138af4f2014-02-07 11:13:45 +053010426 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10427 eCSR_SCAN_ABORT_DEFAULT);
Gopichand Nakkalaaa353782013-05-17 20:36:22 +053010428 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010429
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -080010430#ifdef FEATURE_WLAN_TDLS
10431 /* First clean up the tdls peers if any */
Gopichand Nakkala4327a152013-03-04 23:22:42 -080010432 for (staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++)
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -080010433 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -080010434 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId == pAdapter->sessionId) &&
10435 (pHddCtx->tdlsConnInfo[staIdx].staId))
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -080010436 {
Hoonki Lee11f7dda2013-02-14 16:55:44 -080010437 uint8 *mac;
Gopichand Nakkala4327a152013-03-04 23:22:42 -080010438 mac = pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Hoonki Lee11f7dda2013-02-14 16:55:44 -080010439 VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070010440 "%s: call sme_DeleteTdlsPeerSta staId %d sessionId %d " MAC_ADDRESS_STR,
Gopichand Nakkala4327a152013-03-04 23:22:42 -080010441 __func__, pHddCtx->tdlsConnInfo[staIdx].staId, pAdapter->sessionId,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070010442 MAC_ADDR_ARRAY(mac));
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -080010443 sme_DeleteTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
Gopichand Nakkala4327a152013-03-04 23:22:42 -080010444 pAdapter->sessionId,
10445 mac);
Gopichand Nakkala2a0a1572013-02-10 21:39:16 -080010446 }
10447 }
10448#endif
Arun Kumar Khandavalli94a2bb02013-12-28 19:17:25 +053010449 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"), reasonCode);
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010450 status = wlan_hdd_disconnect(pAdapter, reasonCode);
10451 if ( 0 != status )
Jeff Johnson295189b2012-06-20 16:38:30 -070010452 {
10453 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -080010454 "%s wlan_hdd_disconnect failure, returned %d",
Jeff Johnson295189b2012-06-20 16:38:30 -070010455 __func__, (int)status );
10456 return -EINVAL;
10457 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010458 }
Mahesh A Saptasagar280fd5a2013-12-05 15:38:31 +053010459 else
10460 {
10461 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unexpected cfg disconnect API"
10462 "called while in %d state", __func__,
10463 pHddStaCtx->conn_info.connState);
10464 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010465 }
10466 else
10467 {
10468 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid roam profile", __func__);
10469 }
10470
10471 return status;
10472}
10473
Mahesh A Saptasagarfafb7fe2014-05-16 13:19:37 +053010474static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
10475 struct net_device *dev,
10476 u16 reason
10477 )
10478{
10479 int ret;
10480 vos_ssr_protect(__func__);
10481 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
10482 vos_ssr_unprotect(__func__);
10483
10484 return ret;
10485}
Gopichand Nakkala78a6c812013-05-13 16:39:49 +053010486
Jeff Johnson295189b2012-06-20 16:38:30 -070010487/*
10488 * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010489 * This function is used to initialize the security
Jeff Johnson295189b2012-06-20 16:38:30 -070010490 * settings in IBSS mode.
10491 */
10492static int wlan_hdd_cfg80211_set_privacy_ibss(
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010493 hdd_adapter_t *pAdapter,
Jeff Johnson295189b2012-06-20 16:38:30 -070010494 struct cfg80211_ibss_params *params
10495 )
10496{
10497 int status = 0;
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010498 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070010499 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
10500 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010501
Jeff Johnson295189b2012-06-20 16:38:30 -070010502 ENTER();
10503
10504 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Ravi Joshib58ca0d2013-10-29 09:50:23 -070010505 vos_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Jeff Johnson295189b2012-06-20 16:38:30 -070010506
10507 if (params->ie_len && ( NULL != params->ie) )
10508 {
Shailender Karmuchi67edd312013-06-18 16:30:48 -070010509 if (wlan_hdd_cfg80211_get_ie_ptr (params->ie,
10510 params->ie_len, WLAN_EID_RSN ))
Jeff Johnson295189b2012-06-20 16:38:30 -070010511 {
10512 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
10513 encryptionType = eCSR_ENCRYPT_TYPE_AES;
10514 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -070010515 else if ( hdd_isWPAIEPresent (params->ie, params->ie_len ))
Jeff Johnson295189b2012-06-20 16:38:30 -070010516 {
Shailender Karmuchi642e9812013-05-30 14:34:49 -070010517 tDot11fIEWPA dot11WPAIE;
10518 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Shailender Karmuchi67edd312013-06-18 16:30:48 -070010519 u8 *ie;
Shailender Karmuchi642e9812013-05-30 14:34:49 -070010520
Wilson Yang00256342013-10-10 23:13:38 -070010521 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Shailender Karmuchi67edd312013-06-18 16:30:48 -070010522 ie = wlan_hdd_cfg80211_get_ie_ptr (params->ie,
10523 params->ie_len, DOT11F_EID_WPA);
10524 if ( NULL != ie )
10525 {
10526 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
10527 // Unpack the WPA IE
10528 //Skip past the EID byte and length byte - and four byte WiFi OUI
10529 dot11fUnpackIeWPA((tpAniSirGlobal) halHandle,
10530 &ie[2+4],
10531 ie[1] - 4,
10532 &dot11WPAIE);
10533 /*Extract the multicast cipher, the encType for unicast
10534 cipher for wpa-none is none*/
10535 encryptionType =
10536 hdd_TranslateWPAToCsrEncryptionType(dot11WPAIE.multicast_cipher);
10537 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010538 }
Shailender Karmuchi67edd312013-06-18 16:30:48 -070010539
Jeff Johnson295189b2012-06-20 16:38:30 -070010540 status = wlan_hdd_cfg80211_set_ie(pAdapter, params->ie, params->ie_len);
10541
10542 if (0 > status)
10543 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010544 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE",
Jeff Johnson295189b2012-06-20 16:38:30 -070010545 __func__);
10546 return status;
10547 }
10548 }
10549
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010550 pWextState->roamProfile.AuthType.authType[0] =
10551 pHddStaCtx->conn_info.authType =
Jeff Johnson295189b2012-06-20 16:38:30 -070010552 eCSR_AUTH_TYPE_OPEN_SYSTEM;
10553
10554 if (params->privacy)
10555 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010556 /* Security enabled IBSS, At this time there is no information available
10557 * about the security paramters, so initialise the encryption type to
Jeff Johnson295189b2012-06-20 16:38:30 -070010558 * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010559 * The correct security parameters will be updated later in
Jeff Johnson295189b2012-06-20 16:38:30 -070010560 * wlan_hdd_cfg80211_add_key */
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010561 /* Hal expects encryption type to be set inorder
Jeff Johnson295189b2012-06-20 16:38:30 -070010562 *enable privacy bit in beacons */
10563
10564 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10565 }
Shailender Karmuchi642e9812013-05-30 14:34:49 -070010566 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
10567 "encryptionType=%d", encryptionType);
Jeff Johnson295189b2012-06-20 16:38:30 -070010568 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
10569 pWextState->roamProfile.EncryptionType.numEntries = 1;
10570 pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType;
Jeff Johnson295189b2012-06-20 16:38:30 -070010571 return status;
10572}
10573
10574/*
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053010575 * FUNCTION: __wlan_hdd_cfg80211_join_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010576 * This function is used to create/join an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -070010577 */
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053010578static int __wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -070010579 struct net_device *dev,
10580 struct cfg80211_ibss_params *params
10581 )
10582{
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010583 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Jeff Johnson295189b2012-06-20 16:38:30 -070010584 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10585 tCsrRoamProfile *pRoamProfile;
10586 int status;
krunal sonie9002db2013-11-25 14:24:17 -080010587 bool alloc_bssid = VOS_FALSE;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010588 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10589 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070010590
10591 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010592
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053010593 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10594 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
10595 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010596 hddLog(VOS_TRACE_LEVEL_INFO,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +053010597 "%s: device_mode = %s (%d)", __func__,
10598 hdd_device_modetoString(pAdapter->device_mode),
10599 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -070010600
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010601 status = wlan_hdd_validate_context(pHddCtx);
10602
10603 if (0 != status)
Jeff Johnson295189b2012-06-20 16:38:30 -070010604 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10606 "%s: HDD context is not valid", __func__);
10607 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -070010608 }
10609
10610 if (NULL == pWextState)
10611 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080010612 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -070010613 __func__);
10614 return -EIO;
10615 }
10616
Agarwal Ashish51325b52014-06-16 16:50:49 +053010617 if (vos_max_concurrent_connections_reached()) {
10618 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
10619 return -ECONNREFUSED;
10620 }
10621
Vinay Krishna Eranna21042322014-01-08 19:21:39 +053010622 /*Try disconnecting if already in connected state*/
10623 status = wlan_hdd_try_disconnect(pAdapter);
10624 if ( 0 > status)
10625 {
10626 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to disconnect the existing"
10627 " IBSS connection"));
10628 return -EALREADY;
10629 }
10630
Jeff Johnson295189b2012-06-20 16:38:30 -070010631 pRoamProfile = &pWextState->roamProfile;
10632
10633 if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType )
10634 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010635 hddLog (VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -080010636 "%s Interface type is not set to IBSS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010637 return -EINVAL;
10638 }
10639
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -070010640 /* BSSID is provided by upper layers hence no need to AUTO generate */
10641 if (NULL != params->bssid) {
10642 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
10643 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE) {
10644 hddLog (VOS_TRACE_LEVEL_ERROR,
10645 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
10646 return -EIO;
10647 }
10648 }
krunal sonie9002db2013-11-25 14:24:17 -080010649 else if(pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0)
10650 {
10651 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0,
10652 NULL, eANI_BOOLEAN_FALSE)==eHAL_STATUS_FAILURE)
10653 {
10654 hddLog (VOS_TRACE_LEVEL_ERROR,
10655 "%s:ccmCfgStInt faild for WNI_CFG_IBSS_AUTO_BSSID", __func__);
10656 return -EIO;
10657 }
10658 params->bssid = vos_mem_malloc(sizeof(VOS_MAC_ADDR_SIZE));
10659 if (!params->bssid)
10660 {
10661 hddLog (VOS_TRACE_LEVEL_ERROR,
10662 "%s:Failed memory allocation", __func__);
10663 return -EIO;
10664 }
10665 vos_mem_copy((v_U8_t *)params->bssid,
10666 (v_U8_t *)&pHddCtx->cfg_ini->IbssBssid.bytes[0],
10667 VOS_MAC_ADDR_SIZE);
10668 alloc_bssid = VOS_TRUE;
10669 }
Praveen Kumar Sirisillad123d142013-09-24 16:50:13 -070010670
Jeff Johnson295189b2012-06-20 16:38:30 -070010671 /* Set Channel */
Yue Maf49ba872013-08-19 12:04:25 -070010672 if (NULL !=
10673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
10674 params->chandef.chan)
10675#else
10676 params->channel)
10677#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010678 {
10679 u8 channelNum;
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010680 v_U32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10681 v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10682 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10683 int indx;
Jeff Johnson295189b2012-06-20 16:38:30 -070010684
10685 /* Get channel number */
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010686 channelNum =
Yue Maf49ba872013-08-19 12:04:25 -070010687 ieee80211_frequency_to_channel(
10688#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
10689 params->chandef.chan->center_freq);
10690#else
10691 params->channel->center_freq);
10692#endif
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010693
10694 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10695 validChan, &numChans))
Jeff Johnson295189b2012-06-20 16:38:30 -070010696 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list",
10698 __func__);
10699 return -EOPNOTSUPP;
Jeff Johnson295189b2012-06-20 16:38:30 -070010700 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010701
10702 for (indx = 0; indx < numChans; indx++)
Jeff Johnson295189b2012-06-20 16:38:30 -070010703 {
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010704 if (channelNum == validChan[indx])
10705 {
10706 break;
10707 }
10708 }
10709 if (indx >= numChans)
10710 {
10711 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d",
Jeff Johnson295189b2012-06-20 16:38:30 -070010712 __func__, channelNum);
10713 return -EINVAL;
10714 }
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010715 /* Set the Operational Channel */
10716 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__,
10717 channelNum);
10718 pRoamProfile->ChannelInfo.numOfChannels = 1;
10719 pHddStaCtx->conn_info.operationChannel = channelNum;
10720 pRoamProfile->ChannelInfo.ChannelList =
10721 &pHddStaCtx->conn_info.operationChannel;
Jeff Johnson295189b2012-06-20 16:38:30 -070010722 }
10723
10724 /* Initialize security parameters */
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010725 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
Jeff Johnson295189b2012-06-20 16:38:30 -070010726 if (status < 0)
10727 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010728 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters",
Jeff Johnson295189b2012-06-20 16:38:30 -070010729 __func__);
10730 return status;
10731 }
10732
10733 /* Issue connect start */
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010734 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
Shailender Karmuchi15cd0672013-05-15 19:50:04 -070010735 params->ssid_len, params->bssid,
10736 pHddStaCtx->conn_info.operationChannel);
Jeff Johnson295189b2012-06-20 16:38:30 -070010737
10738 if (0 > status)
10739 {
10740 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__);
10741 return status;
10742 }
10743
krunal sonie9002db2013-11-25 14:24:17 -080010744 if (NULL != params->bssid &&
10745 pHddCtx->cfg_ini->isCoalesingInIBSSAllowed == 0 &&
10746 alloc_bssid == VOS_TRUE)
10747 {
10748 vos_mem_free(params->bssid);
10749 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010750 return 0;
10751}
10752
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053010753static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy,
10754 struct net_device *dev,
10755 struct cfg80211_ibss_params *params
10756 )
10757{
10758 int ret = 0;
10759
10760 vos_ssr_protect(__func__);
10761 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
10762 vos_ssr_unprotect(__func__);
10763
10764 return ret;
10765}
10766
Jeff Johnson295189b2012-06-20 16:38:30 -070010767/*
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053010768 * FUNCTION: __wlan_hdd_cfg80211_leave_ibss
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010769 * This function is used to leave an IBSS
Jeff Johnson295189b2012-06-20 16:38:30 -070010770 */
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053010771static int __wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -070010772 struct net_device *dev
10773 )
10774{
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010775 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010776 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10777 tCsrRoamProfile *pRoamProfile;
10778 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010779 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -070010780
10781 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053010782
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053010783 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10784 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
10785 pAdapter->sessionId, eCSR_DISCONNECT_REASON_IBSS_LEAVE));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010786 status = wlan_hdd_validate_context(pHddCtx);
10787
10788 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070010789 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10791 "%s: HDD context is not valid", __func__);
10792 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070010793 }
10794
Sushant Kaushik8bc7df22014-04-09 17:55:29 +053010795 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %s (%d)", __func__,
10796 hdd_device_modetoString(pAdapter->device_mode),
10797 pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -070010798 if (NULL == pWextState)
10799 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080010800 hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption",
Jeff Johnson295189b2012-06-20 16:38:30 -070010801 __func__);
10802 return -EIO;
10803 }
10804
10805 pRoamProfile = &pWextState->roamProfile;
10806
10807 /* Issue disconnect only if interface type is set to IBSS */
10808 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType)
10809 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010810 hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS",
Jeff Johnson295189b2012-06-20 16:38:30 -070010811 __func__);
10812 return -EINVAL;
10813 }
10814
10815 /* Issue Disconnect request */
10816 INIT_COMPLETION(pAdapter->disconnect_comp_var);
10817 sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
10818 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
10819
10820 return 0;
10821}
10822
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053010823static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy,
10824 struct net_device *dev
10825 )
10826{
10827 int ret = 0;
10828
10829 vos_ssr_protect(__func__);
10830 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
10831 vos_ssr_unprotect(__func__);
10832
10833 return ret;
10834}
10835
Jeff Johnson295189b2012-06-20 16:38:30 -070010836/*
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +053010837 * FUNCTION: __wlan_hdd_cfg80211_set_wiphy_params
Jeff Johnson295189b2012-06-20 16:38:30 -070010838 * This function is used to set the phy parameters
10839 * (RTS Threshold/FRAG Threshold/Retry Count etc ...)
10840 */
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +053010841static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -070010842 u32 changed)
10843{
10844 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10845 tHalHandle hHal = pHddCtx->hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010846 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -070010847
10848 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053010849 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
10850 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
10851 NO_SESSION, wiphy->rts_threshold));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010852 status = wlan_hdd_validate_context(pHddCtx);
10853
10854 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070010855 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10857 "%s: HDD context is not valid", __func__);
10858 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070010859 }
10860
Jeff Johnson295189b2012-06-20 16:38:30 -070010861 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
10862 {
10863 u16 rts_threshold = (wiphy->rts_threshold == -1) ?
10864 WNI_CFG_RTS_THRESHOLD_STAMAX :
10865 wiphy->rts_threshold;
10866
10867 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010868 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold))
Jeff Johnson295189b2012-06-20 16:38:30 -070010869 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010870 hddLog(VOS_TRACE_LEVEL_ERROR,
10871 "%s: Invalid RTS Threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010872 __func__, rts_threshold);
10873 return -EINVAL;
10874 }
10875
10876 if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD,
10877 rts_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010878 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -070010879 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010880 hddLog(VOS_TRACE_LEVEL_ERROR,
10881 "%s: ccmCfgSetInt failed for rts_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010882 __func__, rts_threshold);
10883 return -EIO;
10884 }
10885
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010886 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -070010887 rts_threshold);
10888 }
10889
10890 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
10891 {
10892 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
10893 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
10894 wiphy->frag_threshold;
10895
10896 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)||
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010897 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) )
Jeff Johnson295189b2012-06-20 16:38:30 -070010898 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010899 hddLog(VOS_TRACE_LEVEL_ERROR,
10900 "%s: Invalid frag_threshold value %hu", __func__,
Jeff Johnson295189b2012-06-20 16:38:30 -070010901 frag_threshold);
10902 return -EINVAL;
10903 }
10904
10905 if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
10906 frag_threshold, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010907 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -070010908 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010909 hddLog(VOS_TRACE_LEVEL_ERROR,
10910 "%s: ccmCfgSetInt failed for frag_threshold value %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010911 __func__, frag_threshold);
10912 return -EIO;
10913 }
10914
10915 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set frag threshold %hu", __func__,
10916 frag_threshold);
10917 }
10918
10919 if ((changed & WIPHY_PARAM_RETRY_SHORT)
10920 || (changed & WIPHY_PARAM_RETRY_LONG))
10921 {
10922 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
10923 wiphy->retry_short :
10924 wiphy->retry_long;
10925
10926 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
10927 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value))
10928 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010929 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010930 __func__, retry_value);
10931 return -EINVAL;
10932 }
10933
10934 if (changed & WIPHY_PARAM_RETRY_SHORT)
10935 {
10936 if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT,
10937 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010938 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -070010939 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010940 hddLog(VOS_TRACE_LEVEL_ERROR,
10941 "%s: ccmCfgSetInt failed for long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010942 __func__, retry_value);
10943 return -EIO;
10944 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010945 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010946 __func__, retry_value);
10947 }
10948 else if (changed & WIPHY_PARAM_RETRY_SHORT)
10949 {
10950 if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT,
10951 retry_value, ccmCfgSetCallback,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010952 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -070010953 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010954 hddLog(VOS_TRACE_LEVEL_ERROR,
10955 "%s: ccmCfgSetInt failed for short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010956 __func__, retry_value);
10957 return -EIO;
10958 }
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010959 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu",
Jeff Johnson295189b2012-06-20 16:38:30 -070010960 __func__, retry_value);
10961 }
10962 }
10963
10964 return 0;
10965}
10966
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +053010967static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
10968 u32 changed)
10969{
10970 int ret;
10971
10972 vos_ssr_protect(__func__);
10973 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
10974 vos_ssr_unprotect(__func__);
10975
10976 return ret;
10977}
10978
Jeff Johnson295189b2012-06-20 16:38:30 -070010979/*
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +053010980 * FUNCTION: __wlan_hdd_cfg80211_set_txpower
Jeff Johnson295189b2012-06-20 16:38:30 -070010981 * This function is used to set the txpower
10982 */
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +053010983static int __wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
Yue Maf49ba872013-08-19 12:04:25 -070010984#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
10985 struct wireless_dev *wdev,
10986#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010987#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010988 enum tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -070010989#else
Gopichand Nakkala747461f2013-04-24 19:24:45 +053010990 enum nl80211_tx_power_setting type,
Jeff Johnson295189b2012-06-20 16:38:30 -070010991#endif
10992 int dbm)
10993{
10994 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010995 tHalHandle hHal = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010996 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
10997 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053010998 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -070010999
11000 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011001 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
11002 TRACE_CODE_HDD_CFG80211_SET_TXPOWER,
11003 NO_SESSION, type ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011004 status = wlan_hdd_validate_context(pHddCtx);
11005
11006 if (0 != status)
11007 {
11008 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11009 "%s: HDD context is not valid", __func__);
11010 return status;
11011 }
11012
11013 hHal = pHddCtx->hHal;
11014
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011015 if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL,
11016 dbm, ccmCfgSetCallback,
11017 eANI_BOOLEAN_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -070011018 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011019 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070011020 "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm);
11021 return -EIO;
11022 }
11023
11024 hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__,
11025 dbm);
11026
11027 switch(type)
11028 {
11029 case NL80211_TX_POWER_AUTOMATIC: /*automatically determine transmit power*/
11030 /* Fall through */
11031 case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/
11032 if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS )
11033 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011034 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed",
11035 __func__);
11036 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070011037 }
11038 break;
11039 case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011040 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported",
Jeff Johnson295189b2012-06-20 16:38:30 -070011041 __func__);
11042 return -EOPNOTSUPP;
11043 break;
11044 default:
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011045 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d",
11046 __func__, type);
Jeff Johnson295189b2012-06-20 16:38:30 -070011047 return -EIO;
11048 }
11049
11050 return 0;
11051}
11052
Mahesh A Saptasagar179d2252014-06-02 21:32:21 +053011053static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy,
11054#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
11055 struct wireless_dev *wdev,
11056#endif
11057#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
11058 enum tx_power_setting type,
11059#else
11060 enum nl80211_tx_power_setting type,
11061#endif
11062 int dbm)
11063{
11064 int ret;
11065 vos_ssr_protect(__func__);
11066 ret = __wlan_hdd_cfg80211_set_txpower(wiphy,
11067#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
11068 wdev,
11069#endif
11070#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
11071 type,
11072#else
11073 type,
11074#endif
11075 dbm);
11076 vos_ssr_unprotect(__func__);
11077
11078 return ret;
11079}
11080
Jeff Johnson295189b2012-06-20 16:38:30 -070011081/*
11082 * FUNCTION: wlan_hdd_cfg80211_get_txpower
11083 * This function is used to read the txpower
11084 */
Yue Maf49ba872013-08-19 12:04:25 -070011085static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
11086#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
11087 struct wireless_dev *wdev,
11088#endif
11089 int *dbm)
Jeff Johnson295189b2012-06-20 16:38:30 -070011090{
11091
11092 hdd_adapter_t *pAdapter;
11093 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011094 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -070011095
Jeff Johnsone7245742012-09-05 17:12:55 -070011096 ENTER();
11097
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011098 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011099
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011100 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011101 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11103 "%s: HDD context is not valid", __func__);
11104 *dbm = 0;
11105 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011106 }
11107
Jeff Johnson295189b2012-06-20 16:38:30 -070011108 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
11109 if (NULL == pAdapter)
11110 {
11111 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Not in station context " ,__func__);
11112 return -ENOENT;
11113 }
11114
11115 wlan_hdd_get_classAstats(pAdapter);
11116 *dbm = pAdapter->hdd_stats.ClassA_stat.max_pwr;
11117
Jeff Johnsone7245742012-09-05 17:12:55 -070011118 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070011119 return 0;
11120}
11121
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011122static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -070011123 u8* mac, struct station_info *sinfo)
11124{
11125 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
11126 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11127 int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length;
c_hpothu44ff4e02014-05-08 00:13:57 +053011128 tANI_U32 rate_flags;
Jeff Johnson295189b2012-06-20 16:38:30 -070011129
11130 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
11131 hdd_config_t *pCfg = pHddCtx->cfg_ini;
Jeff Johnson295189b2012-06-20 16:38:30 -070011132
11133 tANI_U8 OperationalRates[CSR_DOT11_SUPPORTED_RATES_MAX];
11134 tANI_U32 ORLeng = CSR_DOT11_SUPPORTED_RATES_MAX;
11135 tANI_U8 ExtendedRates[CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX];
11136 tANI_U32 ERLeng = CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX;
11137 tANI_U8 MCSRates[SIZE_OF_BASIC_MCS_SET];
11138 tANI_U32 MCSLeng = SIZE_OF_BASIC_MCS_SET;
11139 tANI_U16 maxRate = 0;
11140 tANI_U16 myRate;
11141 tANI_U16 currentRate = 0;
11142 tANI_U8 maxSpeedMCS = 0;
11143 tANI_U8 maxMCSIdx = 0;
11144 tANI_U8 rateFlag = 1;
c_hpothu79aab322014-07-14 21:11:01 +053011145 tANI_U8 i, j, rssidx, mode=0;
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -070011146 tANI_U16 temp;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011147 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -070011148
Leo Chang6f8870f2013-03-26 18:11:36 -070011149#ifdef WLAN_FEATURE_11AC
11150 tANI_U32 vht_mcs_map;
11151 eDataRate11ACMaxMcs vhtMaxMcs;
11152#endif /* WLAN_FEATURE_11AC */
11153
Jeff Johnsone7245742012-09-05 17:12:55 -070011154 ENTER();
11155
Jeff Johnson295189b2012-06-20 16:38:30 -070011156 if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) ||
11157 (0 == ssidlen))
11158 {
11159 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Not associated or"
11160 " Invalid ssidlen, %d", __func__, ssidlen);
11161 /*To keep GUI happy*/
11162 return 0;
11163 }
11164
Mukul Sharma811205f2014-07-09 21:07:30 +053011165 if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario)
11166 {
11167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
11168 "%s: Roaming in progress, so unable to proceed this request", __func__);
11169 return 0;
11170 }
11171
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011172 status = wlan_hdd_validate_context(pHddCtx);
11173
11174 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011175 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11177 "%s: HDD context is not valid", __func__);
11178 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011179 }
11180
Jeff Johnson295189b2012-06-20 16:38:30 -070011181
Kiet Lam3b17fc82013-09-27 05:24:08 +053011182 wlan_hdd_get_rssi(pAdapter, &sinfo->signal);
11183 sinfo->filled |= STATION_INFO_SIGNAL;
11184
c_hpothu09f19542014-05-30 21:53:31 +053011185 wlan_hdd_get_station_stats(pAdapter);
11186 rate_flags = pAdapter->hdd_stats.ClassA_stat.tx_rate_flags;
11187
11188 /*overwrite rate_flags if MAX link-speed need to be reported*/
c_hpothu44ff4e02014-05-08 00:13:57 +053011189 if ((eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed) ||
11190 (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed &&
c_hpothu79aab322014-07-14 21:11:01 +053011191 sinfo->signal >= pCfg->linkSpeedRssiLow))
c_hpothu44ff4e02014-05-08 00:13:57 +053011192 {
11193 rate_flags = pAdapter->maxRateFlags;
11194 }
c_hpothu44ff4e02014-05-08 00:13:57 +053011195
Jeff Johnson295189b2012-06-20 16:38:30 -070011196 //convert to the UI units of 100kbps
11197 myRate = pAdapter->hdd_stats.ClassA_stat.tx_rate * 5;
11198
11199#ifdef LINKSPEED_DEBUG_ENABLED
Leo Chang6f8870f2013-03-26 18:11:36 -070011200 pr_info("RSSI %d, RLMS %u, rate %d, rssi high %d, rssi mid %d, rssi low %d, rate_flags 0x%x, MCS %d\n",
Jeff Johnson295189b2012-06-20 16:38:30 -070011201 sinfo->signal,
11202 pCfg->reportMaxLinkSpeed,
11203 myRate,
11204 (int) pCfg->linkSpeedRssiHigh,
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -070011205 (int) pCfg->linkSpeedRssiMid,
11206 (int) pCfg->linkSpeedRssiLow,
Leo Chang6f8870f2013-03-26 18:11:36 -070011207 (int) rate_flags,
11208 (int) pAdapter->hdd_stats.ClassA_stat.mcs_index);
Jeff Johnson295189b2012-06-20 16:38:30 -070011209#endif //LINKSPEED_DEBUG_ENABLED
11210
11211 if (eHDD_LINK_SPEED_REPORT_ACTUAL != pCfg->reportMaxLinkSpeed)
11212 {
11213 // we do not want to necessarily report the current speed
11214 if (eHDD_LINK_SPEED_REPORT_MAX == pCfg->reportMaxLinkSpeed)
11215 {
11216 // report the max possible speed
11217 rssidx = 0;
11218 }
11219 else if (eHDD_LINK_SPEED_REPORT_MAX_SCALED == pCfg->reportMaxLinkSpeed)
11220 {
11221 // report the max possible speed with RSSI scaling
11222 if (sinfo->signal >= pCfg->linkSpeedRssiHigh)
11223 {
11224 // report the max possible speed
11225 rssidx = 0;
11226 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -070011227 else if (sinfo->signal >= pCfg->linkSpeedRssiMid)
Jeff Johnson295189b2012-06-20 16:38:30 -070011228 {
11229 // report middle speed
11230 rssidx = 1;
11231 }
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -070011232 else if (sinfo->signal >= pCfg->linkSpeedRssiLow)
11233 {
11234 // report middle speed
11235 rssidx = 2;
11236 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011237 else
11238 {
11239 // report actual speed
Madan Mohan Koyyalamudi8df78d52012-11-02 12:30:06 -070011240 rssidx = 3;
Jeff Johnson295189b2012-06-20 16:38:30 -070011241 }
11242 }
11243 else
11244 {
11245 // unknown, treat as eHDD_LINK_SPEED_REPORT_MAX
11246 hddLog(VOS_TRACE_LEVEL_ERROR,
11247 "%s: Invalid value for reportMaxLinkSpeed: %u",
11248 __func__, pCfg->reportMaxLinkSpeed);
11249 rssidx = 0;
11250 }
11251
11252 maxRate = 0;
11253
11254 /* Get Basic Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +053011255 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_OPERATIONAL_RATE_SET,
11256 OperationalRates, &ORLeng))
11257 {
11258 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
11259 /*To keep GUI happy*/
11260 return 0;
11261 }
11262
Jeff Johnson295189b2012-06-20 16:38:30 -070011263 for (i = 0; i < ORLeng; i++)
11264 {
Jeff Johnsone7245742012-09-05 17:12:55 -070011265 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -070011266 {
11267 /* Validate Rate Set */
11268 if (supported_data_rate[j].beacon_rate_index == (OperationalRates[i] & 0x7F))
11269 {
11270 currentRate = supported_data_rate[j].supported_rate[rssidx];
11271 break;
11272 }
11273 }
11274 /* Update MAX rate */
11275 maxRate = (currentRate > maxRate)?currentRate:maxRate;
11276 }
11277
11278 /* Get Extended Rate Set */
Gopichand Nakkala05ab1322013-02-15 11:28:38 +053011279 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
11280 ExtendedRates, &ERLeng))
11281 {
11282 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
11283 /*To keep GUI happy*/
11284 return 0;
11285 }
11286
Jeff Johnson295189b2012-06-20 16:38:30 -070011287 for (i = 0; i < ERLeng; i++)
11288 {
Jeff Johnsone7245742012-09-05 17:12:55 -070011289 for (j = 0; j < (sizeof(supported_data_rate) / sizeof(supported_data_rate[0])); j ++)
Jeff Johnson295189b2012-06-20 16:38:30 -070011290 {
11291 if (supported_data_rate[j].beacon_rate_index == (ExtendedRates[i] & 0x7F))
11292 {
11293 currentRate = supported_data_rate[j].supported_rate[rssidx];
11294 break;
11295 }
11296 }
11297 /* Update MAX rate */
11298 maxRate = (currentRate > maxRate)?currentRate:maxRate;
11299 }
c_hpothu79aab322014-07-14 21:11:01 +053011300
Kiet Lamb69f8dc2013-11-15 15:34:27 +053011301 /* Get MCS Rate Set --
Kaushik, Sushantdc304d82014-01-22 10:58:37 +053011302 Only if we are always reporting max speed (or)
Kiet Lamb69f8dc2013-11-15 15:34:27 +053011303 if we have good rssi */
c_hpothu79aab322014-07-14 21:11:01 +053011304 if ((3 != rssidx) && !(rate_flags & eHAL_TX_RATE_LEGACY))
Jeff Johnson295189b2012-06-20 16:38:30 -070011305 {
c_hpothu79aab322014-07-14 21:11:01 +053011306 if (rate_flags & eHAL_TX_RATE_VHT80)
11307 mode = 2;
11308 else if (rate_flags & (eHAL_TX_RATE_VHT40 | eHAL_TX_RATE_HT40))
11309 mode = 1;
11310 else
11311 mode = 0;
11312
Gopichand Nakkala05ab1322013-02-15 11:28:38 +053011313 if (0 != ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_CURRENT_MCS_SET,
11314 MCSRates, &MCSLeng))
11315 {
11316 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: ccm api returned failure", __func__);
11317 /*To keep GUI happy*/
11318 return 0;
11319 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011320 rateFlag = 0;
Leo Chang6f8870f2013-03-26 18:11:36 -070011321#ifdef WLAN_FEATURE_11AC
11322 /* VHT80 rate has seperate rate table */
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011323 if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
Jeff Johnson295189b2012-06-20 16:38:30 -070011324 {
Leo Chang6f8870f2013-03-26 18:11:36 -070011325 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011326 vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
Leo Chang6f8870f2013-03-26 18:11:36 -070011327 if (rate_flags & eHAL_TX_RATE_SGI)
Jeff Johnson295189b2012-06-20 16:38:30 -070011328 {
Leo Chang6f8870f2013-03-26 18:11:36 -070011329 rateFlag |= 1;
Jeff Johnson295189b2012-06-20 16:38:30 -070011330 }
Leo Chang6f8870f2013-03-26 18:11:36 -070011331 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
Jeff Johnson295189b2012-06-20 16:38:30 -070011332 {
Leo Chang6f8870f2013-03-26 18:11:36 -070011333 maxMCSIdx = 7;
11334 }
11335 else if (DATA_RATE_11AC_MAX_MCS_8 == vhtMaxMcs)
11336 {
11337 maxMCSIdx = 8;
11338 }
11339 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
11340 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011341 //VHT20 is supporting 0~8
11342 if (rate_flags & eHAL_TX_RATE_VHT20)
11343 maxMCSIdx = 8;
11344 else
11345 maxMCSIdx = 9;
Leo Chang6f8870f2013-03-26 18:11:36 -070011346 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011347
c_hpothu79aab322014-07-14 21:11:01 +053011348 if (0 != rssidx)/*check for scaled */
11349 {
11350 //get middle rate MCS index if rssi=1/2
11351 for (i=0; i <= maxMCSIdx; i++)
11352 {
11353 if (sinfo->signal <= rssiMcsTbl[mode][i])
11354 {
11355 maxMCSIdx = i;
11356 break;
11357 }
11358 }
11359 }
11360
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011361 if (rate_flags & eHAL_TX_RATE_VHT80)
11362 {
11363 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
11364 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
11365 }
11366 else if (rate_flags & eHAL_TX_RATE_VHT40)
11367 {
11368 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
11369 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
11370 }
11371 else if (rate_flags & eHAL_TX_RATE_VHT20)
11372 {
11373 currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
11374 maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
11375 }
11376
Leo Chang6f8870f2013-03-26 18:11:36 -070011377 maxSpeedMCS = 1;
11378 if (currentRate > maxRate)
11379 {
11380 maxRate = currentRate;
11381 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011382
Leo Chang6f8870f2013-03-26 18:11:36 -070011383 }
11384 else
11385#endif /* WLAN_FEATURE_11AC */
11386 {
11387 if (rate_flags & eHAL_TX_RATE_HT40)
11388 {
11389 rateFlag |= 1;
11390 }
11391 if (rate_flags & eHAL_TX_RATE_SGI)
11392 {
11393 rateFlag |= 2;
11394 }
11395
c_hpothu79aab322014-07-14 21:11:01 +053011396 if (rssidx == 1 || rssidx == 2)
11397 {
11398 //get middle rate MCS index if rssi=1/2
11399 for (i=0; i <= 7; i++)
11400 {
11401 if (sinfo->signal <= rssiMcsTbl[mode][i])
11402 {
11403 temp = i+1;
11404 break;
11405 }
11406 }
11407 }
11408 else
Leo Chang6f8870f2013-03-26 18:11:36 -070011409 {
11410 temp = sizeof(supported_mcs_rate) / sizeof(supported_mcs_rate[0]);
c_hpothu79aab322014-07-14 21:11:01 +053011411 }
11412
11413 for (i = 0; i < MCSLeng; i++)
11414 {
Leo Chang6f8870f2013-03-26 18:11:36 -070011415 for (j = 0; j < temp; j++)
11416 {
11417 if (supported_mcs_rate[j].beacon_rate_index == MCSRates[i])
11418 {
11419 currentRate = supported_mcs_rate[j].supported_rate[rateFlag];
11420 break;
11421 }
11422 }
11423 if ((j < temp) && (currentRate > maxRate))
11424 {
11425 maxRate = currentRate;
11426 maxSpeedMCS = 1;
11427 maxMCSIdx = supported_mcs_rate[j].beacon_rate_index;
11428 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011429 }
11430 }
11431 }
11432
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011433 else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
11434 {
11435 maxRate = myRate;
11436 maxSpeedMCS = 1;
11437 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
11438 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011439 // make sure we report a value at least as big as our current rate
c_hpothu79aab322014-07-14 21:11:01 +053011440 if ((maxRate < myRate) || (0 == maxRate))
Jeff Johnson295189b2012-06-20 16:38:30 -070011441 {
11442 maxRate = myRate;
11443 if (rate_flags & eHAL_TX_RATE_LEGACY)
11444 {
11445 maxSpeedMCS = 0;
11446 }
11447 else
11448 {
11449 maxSpeedMCS = 1;
11450 maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
11451 }
11452 }
11453
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011454 if (rate_flags & eHAL_TX_RATE_LEGACY)
Jeff Johnson295189b2012-06-20 16:38:30 -070011455 {
11456 sinfo->txrate.legacy = maxRate;
11457#ifdef LINKSPEED_DEBUG_ENABLED
11458 pr_info("Reporting legacy rate %d\n", sinfo->txrate.legacy);
11459#endif //LINKSPEED_DEBUG_ENABLED
11460 }
11461 else
11462 {
11463 sinfo->txrate.mcs = maxMCSIdx;
Leo Chang6f8870f2013-03-26 18:11:36 -070011464#ifdef WLAN_FEATURE_11AC
11465 sinfo->txrate.nss = 1;
11466 if (rate_flags & eHAL_TX_RATE_VHT80)
11467 {
11468 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011469 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Leo Chang6f8870f2013-03-26 18:11:36 -070011470 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011471 else if (rate_flags & eHAL_TX_RATE_VHT40)
Leo Chang6f8870f2013-03-26 18:11:36 -070011472 {
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011473 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
11474 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
11475 }
11476 else if (rate_flags & eHAL_TX_RATE_VHT20)
11477 {
11478 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
11479 }
11480#endif /* WLAN_FEATURE_11AC */
11481 if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
11482 {
11483 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
11484 if (rate_flags & eHAL_TX_RATE_HT40)
11485 {
11486 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
11487 }
Leo Chang6f8870f2013-03-26 18:11:36 -070011488 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011489 if (rate_flags & eHAL_TX_RATE_SGI)
11490 {
11491 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
11492 }
Gopichand Nakkala4c705372013-04-24 13:20:33 +053011493
Jeff Johnson295189b2012-06-20 16:38:30 -070011494#ifdef LINKSPEED_DEBUG_ENABLED
11495 pr_info("Reporting MCS rate %d flags %x\n",
11496 sinfo->txrate.mcs,
11497 sinfo->txrate.flags );
11498#endif //LINKSPEED_DEBUG_ENABLED
11499 }
11500 }
11501 else
11502 {
11503 // report current rate instead of max rate
11504
11505 if (rate_flags & eHAL_TX_RATE_LEGACY)
11506 {
11507 //provide to the UI in units of 100kbps
11508 sinfo->txrate.legacy = myRate;
11509#ifdef LINKSPEED_DEBUG_ENABLED
11510 pr_info("Reporting actual legacy rate %d\n", sinfo->txrate.legacy);
11511#endif //LINKSPEED_DEBUG_ENABLED
11512 }
11513 else
11514 {
11515 //must be MCS
11516 sinfo->txrate.mcs = pAdapter->hdd_stats.ClassA_stat.mcs_index;
Leo Chang6f8870f2013-03-26 18:11:36 -070011517#ifdef WLAN_FEATURE_11AC
11518 sinfo->txrate.nss = 1;
11519 if (rate_flags & eHAL_TX_RATE_VHT80)
11520 {
11521 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
11522 }
11523 else
11524#endif /* WLAN_FEATURE_11AC */
11525 {
11526 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
11527 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011528 if (rate_flags & eHAL_TX_RATE_SGI)
11529 {
11530 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
11531 }
11532 if (rate_flags & eHAL_TX_RATE_HT40)
11533 {
11534 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
11535 }
Leo Chang6f8870f2013-03-26 18:11:36 -070011536#ifdef WLAN_FEATURE_11AC
11537 else if (rate_flags & eHAL_TX_RATE_VHT80)
11538 {
11539 sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
11540 }
11541#endif /* WLAN_FEATURE_11AC */
Jeff Johnson295189b2012-06-20 16:38:30 -070011542#ifdef LINKSPEED_DEBUG_ENABLED
11543 pr_info("Reporting actual MCS rate %d flags %x\n",
11544 sinfo->txrate.mcs,
11545 sinfo->txrate.flags );
11546#endif //LINKSPEED_DEBUG_ENABLED
11547 }
11548 }
11549 sinfo->filled |= STATION_INFO_TX_BITRATE;
11550
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -070011551 sinfo->tx_packets =
11552 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[0] +
11553 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[1] +
11554 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[2] +
11555 pAdapter->hdd_stats.summary_stat.tx_frm_cnt[3];
11556
11557 sinfo->tx_retries =
11558 pAdapter->hdd_stats.summary_stat.retry_cnt[0] +
11559 pAdapter->hdd_stats.summary_stat.retry_cnt[1] +
11560 pAdapter->hdd_stats.summary_stat.retry_cnt[2] +
11561 pAdapter->hdd_stats.summary_stat.retry_cnt[3];
11562
11563 sinfo->tx_failed =
11564 pAdapter->hdd_stats.summary_stat.fail_cnt[0] +
11565 pAdapter->hdd_stats.summary_stat.fail_cnt[1] +
11566 pAdapter->hdd_stats.summary_stat.fail_cnt[2] +
11567 pAdapter->hdd_stats.summary_stat.fail_cnt[3];
11568
11569 sinfo->filled |=
11570 STATION_INFO_TX_PACKETS |
11571 STATION_INFO_TX_RETRIES |
11572 STATION_INFO_TX_FAILED;
11573
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011574 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
11575 TRACE_CODE_HDD_CFG80211_GET_STA,
11576 pAdapter->sessionId, maxRate));
Madan Mohan Koyyalamudi4d4d2812012-09-24 14:08:29 -070011577 EXIT();
11578 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011579}
11580
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011581static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
11582 u8* mac, struct station_info *sinfo)
11583{
11584 int ret;
11585
11586 vos_ssr_protect(__func__);
11587 ret = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo);
11588 vos_ssr_unprotect(__func__);
11589
11590 return ret;
11591}
11592
11593static int __wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
Sameer Thalappilc9f26e92013-06-07 10:11:06 -070011594 struct net_device *dev, bool mode, int timeout)
Jeff Johnson295189b2012-06-20 16:38:30 -070011595{
11596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053011597 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070011598 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011599 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -070011600
Jeff Johnsone7245742012-09-05 17:12:55 -070011601 ENTER();
11602
Jeff Johnson295189b2012-06-20 16:38:30 -070011603 if (NULL == pAdapter)
11604 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011605 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011606 return -ENODEV;
11607 }
11608
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011609 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
11610 TRACE_CODE_HDD_CFG80211_SET_POWER_MGMT,
11611 pAdapter->sessionId, timeout));
11612
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053011613 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011614 status = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053011615
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011616 if (0 != status)
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011617 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11619 "%s: HDD context is not valid", __func__);
11620 return status;
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011621 }
11622
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053011623 if ((DRIVER_POWER_MODE_AUTO == !mode) &&
11624 (TRUE == pHddCtx->hdd_wlan_suspended) &&
11625 (pHddCtx->cfg_ini->fhostArpOffload) &&
11626 (eConnectionState_Associated ==
11627 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState))
11628 {
Amar Singhald53568e2013-09-26 11:03:45 -070011629
11630 hddLog(VOS_TRACE_LEVEL_INFO,
11631 "offload: in cfg80211_set_power_mgmt, calling arp offload");
Gopichand Nakkalab03e8082013-05-30 18:09:25 +053011632 vos_status = hdd_conf_arp_offload(pAdapter, TRUE);
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053011633 if (!VOS_IS_STATUS_SUCCESS(vos_status))
11634 {
11635 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -080011636 "%s:Failed to enable ARPOFFLOAD Feature %d",
Gopichand Nakkala20c4c042013-04-19 22:08:55 +053011637 __func__, vos_status);
11638 }
11639 }
11640
Jeff Johnson295189b2012-06-20 16:38:30 -070011641 /**The get power cmd from the supplicant gets updated by the nl only
11642 *on successful execution of the function call
11643 *we are oppositely mapped w.r.t mode in the driver
11644 **/
11645 vos_status = wlan_hdd_enter_bmps(pAdapter, !mode);
11646
Kiet Lam94fd2922014-06-18 19:12:43 -070011647 if (!mode)
11648 {
11649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
11650 "%s: DHCP start indicated through power save", __func__);
11651
11652 pHddCtx->btCoexModeSet = TRUE;
11653 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
11654 pAdapter->sessionId);
11655 }
11656 else
11657 {
11658 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
11659 "%s: DHCP stop indicated through power save", __func__);
11660
11661 pHddCtx->btCoexModeSet = FALSE;
11662 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
11663 pAdapter->sessionId);
11664 }
11665
Jeff Johnsone7245742012-09-05 17:12:55 -070011666 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070011667 if (VOS_STATUS_E_FAILURE == vos_status)
11668 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11670 "%s: failed to enter bmps mode", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011671 return -EINVAL;
11672 }
11673 return 0;
11674}
11675
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011676static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy,
11677 struct net_device *dev, bool mode, int timeout)
11678{
11679 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070011680
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011681 vos_ssr_protect(__func__);
11682 ret = __wlan_hdd_cfg80211_set_power_mgmt(wiphy, dev, mode, timeout);
11683 vos_ssr_unprotect(__func__);
11684
11685 return ret;
11686}
Jeff Johnson295189b2012-06-20 16:38:30 -070011687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
11688static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
11689 struct net_device *netdev,
11690 u8 key_index)
11691{
Jeff Johnsone7245742012-09-05 17:12:55 -070011692 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070011693 return 0;
11694}
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011695#endif //LINUX_VERSION_CODE
Jeff Johnson295189b2012-06-20 16:38:30 -070011696
11697#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
11698static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
11699 struct net_device *dev,
11700 struct ieee80211_txq_params *params)
11701{
Jeff Johnsone7245742012-09-05 17:12:55 -070011702 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070011703 return 0;
11704}
11705#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
11706static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
11707 struct ieee80211_txq_params *params)
11708{
Jeff Johnsone7245742012-09-05 17:12:55 -070011709 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070011710 return 0;
11711}
11712#endif //LINUX_VERSION_CODE
11713
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011714static int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -070011715 struct net_device *dev, u8 *mac)
11716{
11717 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011718 hdd_context_t *pHddCtx;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011719 VOS_STATUS vos_status;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011720 int status;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011721 v_U8_t staId;
Jeff Johnson295189b2012-06-20 16:38:30 -070011722
Jeff Johnsone7245742012-09-05 17:12:55 -070011723 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011724
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011725 if ( NULL == pAdapter )
Jeff Johnson295189b2012-06-20 16:38:30 -070011726 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011727 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011728 return -EINVAL;
11729 }
11730
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011731 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
11732 TRACE_CODE_HDD_CFG80211_DEL_STA,
11733 pAdapter->sessionId, pAdapter->device_mode));
11734
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011735 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11736 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011737
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011738 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011739 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11741 "%s: HDD context is not valid", __func__);
11742 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011743 }
11744
Jeff Johnson295189b2012-06-20 16:38:30 -070011745 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -070011746 || (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -070011747 )
11748 {
11749 if( NULL == mac )
11750 {
11751 v_U16_t i;
11752 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
11753 {
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070011754 if ((pAdapter->aStaInfo[i].isUsed) &&
11755 (!pAdapter->aStaInfo[i].isDeauthInProgress))
Jeff Johnson295189b2012-06-20 16:38:30 -070011756 {
11757 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
11758 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -080011759 "%s: Delete STA with MAC::"
11760 MAC_ADDRESS_STR,
11761 __func__, MAC_ADDR_ARRAY(macAddr));
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070011762 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
11763 if (VOS_IS_STATUS_SUCCESS(vos_status))
11764 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070011765 }
11766 }
11767 }
11768 else
11769 {
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011770
11771 vos_status = hdd_softap_GetStaId(pAdapter,(v_MACADDR_t *)mac, &staId);
11772 if (!VOS_IS_STATUS_SUCCESS(vos_status))
11773 {
11774 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -080011775 "%s: Skip this DEL STA as this is not used::"
11776 MAC_ADDRESS_STR,
11777 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011778 return -ENOENT;
11779 }
11780
11781 if( pAdapter->aStaInfo[staId].isDeauthInProgress == TRUE)
11782 {
11783 hddLog(VOS_TRACE_LEVEL_INFO,
Arif Hussain24bafea2013-11-15 15:10:03 -080011784 "%s: Skip this DEL STA as deauth is in progress::"
11785 MAC_ADDRESS_STR,
11786 __func__, MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011787 return -ENOENT;
11788 }
11789
11790 pAdapter->aStaInfo[staId].isDeauthInProgress = TRUE;
11791
Jeff Johnson295189b2012-06-20 16:38:30 -070011792 hddLog(VOS_TRACE_LEVEL_INFO,
11793 "%s: Delete STA with MAC::"
Arif Hussain24bafea2013-11-15 15:10:03 -080011794 MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -070011795 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -080011796 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011797
11798 vos_status = hdd_softap_sta_deauth(pAdapter, mac);
11799 if (!VOS_IS_STATUS_SUCCESS(vos_status))
11800 {
11801 pAdapter->aStaInfo[staId].isDeauthInProgress = FALSE;
11802 hddLog(VOS_TRACE_LEVEL_INFO,
11803 "%s: STA removal failed for ::"
Arif Hussain24bafea2013-11-15 15:10:03 -080011804 MAC_ADDRESS_STR,
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011805 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -080011806 MAC_ADDR_ARRAY(mac));
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080011807 return -ENOENT;
11808 }
11809
Jeff Johnson295189b2012-06-20 16:38:30 -070011810 }
11811 }
11812
11813 EXIT();
11814
11815 return 0;
11816}
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011817static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
11818 struct net_device *dev, u8 *mac)
11819{
11820 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070011821
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011822 vos_ssr_protect(__func__);
11823 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, mac);
11824 vos_ssr_unprotect(__func__);
11825
11826 return ret;
11827}
11828
11829static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
Hoonki Lee11f7dda2013-02-14 16:55:44 -080011830 struct net_device *dev, u8 *mac, struct station_parameters *params)
11831{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011832 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkalab977a972013-02-18 19:15:09 -080011833 int status = -EPERM;
Hoonki Lee11f7dda2013-02-14 16:55:44 -080011834#ifdef FEATURE_WLAN_TDLS
11835 u32 mask, set;
Hoonki Lee11f7dda2013-02-14 16:55:44 -080011836 ENTER();
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053011837
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011838 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
11839 TRACE_CODE_HDD_CFG80211_ADD_STA,
11840 pAdapter->sessionId, params->listen_interval));
Mohit Khanna698ba2a2012-12-04 15:08:18 -080011841 mask = params->sta_flags_mask;
11842
11843 set = params->sta_flags_set;
11844
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070011845#ifdef WLAN_FEATURE_TDLS_DEBUG
11846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11847 "%s: mask 0x%x set 0x%x " MAC_ADDRESS_STR,
11848 __func__, mask, set, MAC_ADDR_ARRAY(mac));
11849#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -080011850
11851 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
11852 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Gopichand Nakkala681989c2013-03-06 22:27:48 -080011853 status = wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080011854 }
11855 }
11856#endif
Gopichand Nakkalab977a972013-02-18 19:15:09 -080011857 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -070011858}
11859
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011860static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
11861 struct net_device *dev, u8 *mac, struct station_parameters *params)
11862{
11863 int ret;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011864
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053011865 vos_ssr_protect(__func__);
11866 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
11867 vos_ssr_unprotect(__func__);
11868
11869 return ret;
11870}
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011871#ifdef FEATURE_WLAN_LFR
Wilson Yang6507c4e2013-10-01 20:11:19 -070011872
Mahesh A Saptasagarf7418d72014-06-02 14:48:54 +053011873static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
Jeff Johnsond13512a2012-07-17 11:42:19 -070011874 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011875{
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011876 tANI_U32 j=0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011877 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Agarwal Ashish3da95242014-05-21 14:57:17 +053011878 hdd_station_ctx_t *pHddStaCtx;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011879 tHalHandle halHandle;
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011880 eHalStatus result;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011881 int status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011882 tANI_U8 BSSIDMatched = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011883 hdd_context_t *pHddCtx;
Jeff Johnson0299d0a2013-10-30 12:37:43 -070011884 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: set PMKSA for " MAC_ADDRESS_STR,
11885 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Jeff Johnsone7245742012-09-05 17:12:55 -070011886
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011887 // Validate pAdapter
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011888 if ( NULL == pAdapter )
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011889 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011890 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011891 return -EINVAL;
11892 }
11893
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011894 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11895 status = wlan_hdd_validate_context(pHddCtx);
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011896
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011897 if (0 != status)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011898 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053011899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11900 "%s: HDD context is not valid", __func__);
11901 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011902 }
11903
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011904 // Retrieve halHandle
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011905 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Agarwal Ashish3da95242014-05-21 14:57:17 +053011906 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011907
Agarwal Ashish3da95242014-05-21 14:57:17 +053011908 for (j = 0; j < pHddStaCtx->PMKIDCacheIndex; j++)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011909 {
Agarwal Ashish3da95242014-05-21 14:57:17 +053011910 if (vos_mem_compare(pHddStaCtx->PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011911 pmksa->bssid, WNI_CFG_BSSID_LEN))
11912 {
11913 /* BSSID matched previous entry. Overwrite it. */
11914 BSSIDMatched = 1;
Agarwal Ashish3da95242014-05-21 14:57:17 +053011915 vos_mem_copy(pHddStaCtx->PMKIDCache[j].BSSID,
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011916 pmksa->bssid, WNI_CFG_BSSID_LEN);
Agarwal Ashish3da95242014-05-21 14:57:17 +053011917 vos_mem_copy(pHddStaCtx->PMKIDCache[j].PMKID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011918 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011919 CSR_RSN_PMKID_SIZE);
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011920 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011921 __func__, j );
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011922 dump_bssid(pmksa->bssid);
11923 dump_pmkid(halHandle, pmksa->pmkid);
11924 break;
11925 }
11926 }
11927
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -070011928 /* Check we compared all entries,if then take the first slot now */
Agarwal Ashish3da95242014-05-21 14:57:17 +053011929 if (j == MAX_PMKSAIDS_IN_CACHE) pHddStaCtx->PMKIDCacheIndex=0;
Madan Mohan Koyyalamudic4b317d2012-10-18 19:43:08 -070011930
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011931 if (!BSSIDMatched)
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011932 {
11933 // Now, we DON'T have a BSSID match, so take a new entry in the cache.
Agarwal Ashish3da95242014-05-21 14:57:17 +053011934 vos_mem_copy(pHddStaCtx->PMKIDCache[pHddStaCtx->PMKIDCacheIndex].BSSID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011935 pmksa->bssid, ETHER_ADDR_LEN);
Agarwal Ashish3da95242014-05-21 14:57:17 +053011936 vos_mem_copy(pHddStaCtx->PMKIDCache[pHddStaCtx->PMKIDCacheIndex].PMKID,
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011937 pmksa->pmkid,
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011938 CSR_RSN_PMKID_SIZE);
Agarwal Ashish3da95242014-05-21 14:57:17 +053011939 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: Adding a new cache entry %d.",
11940 __func__, pHddStaCtx->PMKIDCacheIndex );
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011941 dump_bssid(pmksa->bssid);
11942 dump_pmkid(halHandle, pmksa->pmkid);
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011943 // Increment the HDD Local Cache index
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011944 // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME
Agarwal Ashish3da95242014-05-21 14:57:17 +053011945 if (pHddStaCtx->PMKIDCacheIndex <= (MAX_PMKSAIDS_IN_CACHE-1))
11946 pHddStaCtx->PMKIDCacheIndex++;
11947 else
11948 pHddStaCtx->PMKIDCacheIndex = 0;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011949 }
11950
11951
11952 // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache
Agarwal Ashish3da95242014-05-21 14:57:17 +053011953 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.",
11954 __func__, pHddStaCtx->PMKIDCacheIndex );
11955
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011956 // Finally set the PMKSA ID Cache in CSR
Gopichand Nakkala747461f2013-04-24 19:24:45 +053011957 result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId,
Agarwal Ashish3da95242014-05-21 14:57:17 +053011958 pHddStaCtx->PMKIDCache,
11959 pHddStaCtx->PMKIDCacheIndex);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053011960 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
11961 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
11962 pAdapter->sessionId, result));
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011963 return 0;
11964}
11965
Mahesh A Saptasagarf7418d72014-06-02 14:48:54 +053011966static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
11967 struct cfg80211_pmksa *pmksa)
11968{
11969 int ret;
11970
11971 vos_ssr_protect(__func__);
11972 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
11973 vos_ssr_unprotect(__func__);
11974
11975 return ret;
11976}
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011977
Wilson Yang6507c4e2013-10-01 20:11:19 -070011978
Mahesh A Saptasagarf7418d72014-06-02 14:48:54 +053011979static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
Wilson Yang6507c4e2013-10-01 20:11:19 -070011980 struct cfg80211_pmksa *pmksa)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070011981{
Wilson Yang6507c4e2013-10-01 20:11:19 -070011982 tANI_U32 j=0;
11983 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Agarwal Ashish3da95242014-05-21 14:57:17 +053011984 hdd_station_ctx_t *pHddStaCtx;
Wilson Yang6507c4e2013-10-01 20:11:19 -070011985 tHalHandle halHandle;
Wilson Yang6507c4e2013-10-01 20:11:19 -070011986 tANI_U8 BSSIDMatched = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -070011987 hdd_context_t *pHddCtx;
Wilson Yangef657d32014-01-15 19:19:23 -080011988 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -070011989
Jeff Johnson0299d0a2013-10-30 12:37:43 -070011990 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: deleting PMKSA for " MAC_ADDRESS_STR,
11991 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -070011992
11993 /* Validate pAdapter */
11994 if (NULL == pAdapter)
11995 {
11996 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__);
11997 return -EINVAL;
11998 }
11999
12000 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12001 status = wlan_hdd_validate_context(pHddCtx);
12002
12003 if (0 != status)
12004 {
12005 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12006 "%s: HDD context is not valid", __func__);
12007 return status;
12008 }
12009
12010 /*Retrieve halHandle*/
12011 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Agarwal Ashish3da95242014-05-21 14:57:17 +053012012 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Wilson Yang6507c4e2013-10-01 20:11:19 -070012013
12014 /*in case index is 0,no entry to delete*/
Agarwal Ashish3da95242014-05-21 14:57:17 +053012015 if (0 == pHddStaCtx->PMKIDCacheIndex)
Wilson Yang6507c4e2013-10-01 20:11:19 -070012016 {
Agarwal Ashish3da95242014-05-21 14:57:17 +053012017 hddLog(VOS_TRACE_LEVEL_INFO, FL("No entries to flush"));
12018 return 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012019 }
12020
12021 /*find the matching PMKSA entry from j=0 to (index-1),
12022 * and delete the matched one
12023 */
Agarwal Ashish3da95242014-05-21 14:57:17 +053012024 for (j = 0; j < pHddStaCtx->PMKIDCacheIndex; j++)
Wilson Yang6507c4e2013-10-01 20:11:19 -070012025 {
Agarwal Ashish3da95242014-05-21 14:57:17 +053012026 if (vos_mem_compare(pHddStaCtx->PMKIDCache[j].BSSID,
Wilson Yang6507c4e2013-10-01 20:11:19 -070012027 pmksa->bssid,
12028 WNI_CFG_BSSID_LEN))
12029 {
12030 /* BSSID matched entry */
12031 BSSIDMatched = 1;
Agarwal Ashish3da95242014-05-21 14:57:17 +053012032 if (j < pHddStaCtx->PMKIDCacheIndex-1)
Wilson Yang6507c4e2013-10-01 20:11:19 -070012033 {
12034 /*replace the matching entry with the last entry in HDD local cache*/
Agarwal Ashish3da95242014-05-21 14:57:17 +053012035 vos_mem_copy(pHddStaCtx->PMKIDCache[j].BSSID,
12036 pHddStaCtx->PMKIDCache[pHddStaCtx->PMKIDCacheIndex-1].BSSID,
12037 VOS_MAC_ADDR_SIZE);
12038 vos_mem_copy(pHddStaCtx->PMKIDCache[j].PMKID,
12039 pHddStaCtx->PMKIDCache[pHddStaCtx->PMKIDCacheIndex-1].PMKID,
12040 CSR_RSN_PMKID_SIZE);
12041 }
Wilson Yang6507c4e2013-10-01 20:11:19 -070012042
12043 /*clear the last entry in HDD cache ---[index-1]*/
Agarwal Ashish3da95242014-05-21 14:57:17 +053012044 vos_mem_zero(pHddStaCtx->PMKIDCache[pHddStaCtx->PMKIDCacheIndex-1].BSSID,
12045 VOS_MAC_ADDR_SIZE);
12046 vos_mem_zero(pHddStaCtx->PMKIDCache[pHddStaCtx->PMKIDCacheIndex-1].PMKID,
12047 CSR_RSN_PMKID_SIZE);
Wilson Yang6507c4e2013-10-01 20:11:19 -070012048 /*reduce the PMKID array index*/
Agarwal Ashish3da95242014-05-21 14:57:17 +053012049 pHddStaCtx->PMKIDCacheIndex--;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012050 /*delete the last PMKID cache in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -080012051 if (eHAL_STATUS_SUCCESS !=
12052 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pmksa->bssid))
Wilson Yang6507c4e2013-10-01 20:11:19 -070012053 {
12054 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cannot delete PMKSA %d CONTENT.",
Agarwal Ashish3da95242014-05-21 14:57:17 +053012055 __func__, pHddStaCtx->PMKIDCacheIndex);
Wilson Yangef657d32014-01-15 19:19:23 -080012056 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012057 }
12058
12059 dump_bssid(pmksa->bssid);
12060 dump_pmkid(halHandle,pmksa->pmkid);
12061
12062 break;
12063 }
12064 }
12065
12066 /* we compare all entries,but cannot find matching entry */
12067 if (j == MAX_PMKSAIDS_IN_CACHE && !BSSIDMatched)
12068 {
Jeff Johnson0299d0a2013-10-30 12:37:43 -070012069 hddLog(VOS_TRACE_LEVEL_FATAL,
12070 "%s: No such PMKSA entry existed " MAC_ADDRESS_STR,
12071 __func__, MAC_ADDR_ARRAY(pmksa->bssid));
Wilson Yang6507c4e2013-10-01 20:11:19 -070012072 dump_bssid(pmksa->bssid);
12073 dump_pmkid(halHandle, pmksa->pmkid);
12074 return -EINVAL;
12075 }
Wilson Yangef657d32014-01-15 19:19:23 -080012076 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070012077}
12078
Wilson Yang6507c4e2013-10-01 20:11:19 -070012079
Mahesh A Saptasagarf7418d72014-06-02 14:48:54 +053012080static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
12081 struct cfg80211_pmksa *pmksa)
12082{
12083 int ret;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012084
Mahesh A Saptasagarf7418d72014-06-02 14:48:54 +053012085 vos_ssr_protect(__func__);
12086 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
12087 vos_ssr_unprotect(__func__);
12088
12089 return ret;
12090
12091}
12092
12093static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
Jeff Johnson04dd8a82012-06-29 20:41:40 -070012094{
Wilson Yang6507c4e2013-10-01 20:11:19 -070012095 tANI_U32 j=0;
12096 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Agarwal Ashish3da95242014-05-21 14:57:17 +053012097 hdd_station_ctx_t *pHddStaCtx;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012098 tHalHandle halHandle;
12099 hdd_context_t *pHddCtx;
12100 tANI_U8 *pBSSId;
Wilson Yangef657d32014-01-15 19:19:23 -080012101 int status = 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012102
12103 hddLog(VOS_TRACE_LEVEL_DEBUG, "%s: flushing PMKSA ",__func__);
12104
12105 /* Validate pAdapter */
12106 if (NULL == pAdapter)
12107 {
12108 hddLog(VOS_TRACE_LEVEL_ERROR,
12109 "%s: Invalid Adapter" ,__func__);
12110 return -EINVAL;
12111 }
12112
12113 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12114 status = wlan_hdd_validate_context(pHddCtx);
12115
12116 if (0 != status)
12117 {
12118 hddLog(VOS_TRACE_LEVEL_ERROR,
12119 "%s: HDD context is not valid", __func__);
12120 return status;
12121 }
12122
12123 /*Retrieve halHandle*/
12124 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
Agarwal Ashish3da95242014-05-21 14:57:17 +053012125 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Wilson Yang6507c4e2013-10-01 20:11:19 -070012126
12127 /*in case index is 0,no entry to delete*/
Agarwal Ashish3da95242014-05-21 14:57:17 +053012128 if (0 == pHddStaCtx->PMKIDCacheIndex)
Wilson Yang6507c4e2013-10-01 20:11:19 -070012129 {
Vinay Krishna Erannacbf75f42014-02-26 17:35:20 +053012130 hddLog(VOS_TRACE_LEVEL_ERROR, FL("No entries to flush"));
Agarwal Ashish3da95242014-05-21 14:57:17 +053012131 return 0;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012132 }
12133
12134 /*delete all the PMKSA one by one */
Agarwal Ashish3da95242014-05-21 14:57:17 +053012135 for (j = 0; j < pHddStaCtx->PMKIDCacheIndex; j++)
Wilson Yang6507c4e2013-10-01 20:11:19 -070012136 {
Agarwal Ashish3da95242014-05-21 14:57:17 +053012137 pBSSId =(tANI_U8 *)(pHddStaCtx->PMKIDCache[j].BSSID);
Wilson Yang6507c4e2013-10-01 20:11:19 -070012138 /*delete the PMKID in CSR*/
Wilson Yangef657d32014-01-15 19:19:23 -080012139 if (eHAL_STATUS_SUCCESS !=
12140 sme_RoamDelPMKIDfromCache(halHandle, pAdapter->sessionId, pBSSId))
Wilson Yang6507c4e2013-10-01 20:11:19 -070012141 {
12142 hddLog(VOS_TRACE_LEVEL_ERROR ,"%s cannot flush PMKIDCache %d.",
12143 __func__,j);
Wilson Yangef657d32014-01-15 19:19:23 -080012144 status = -EINVAL;
Wilson Yang6507c4e2013-10-01 20:11:19 -070012145 }
Kiet Lam8d21d5b2013-10-31 17:18:29 +053012146 /*clear the entry in HDD cache 0--index-1 */
Agarwal Ashish3da95242014-05-21 14:57:17 +053012147 vos_mem_zero(pHddStaCtx->PMKIDCache[j].BSSID, VOS_MAC_ADDR_SIZE);
12148 vos_mem_zero(pHddStaCtx->PMKIDCache[j].PMKID, CSR_RSN_PMKID_SIZE);
12149 }
Wilson Yang6507c4e2013-10-01 20:11:19 -070012150
Agarwal Ashish3da95242014-05-21 14:57:17 +053012151 pHddStaCtx->PMKIDCacheIndex = 0;
Wilson Yangef657d32014-01-15 19:19:23 -080012152 return status;
Jeff Johnson04dd8a82012-06-29 20:41:40 -070012153}
Mahesh A Saptasagarf7418d72014-06-02 14:48:54 +053012154
12155static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
12156{
12157 int ret;
12158
12159 vos_ssr_protect(__func__);
12160 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
12161 vos_ssr_unprotect(__func__);
12162
12163 return ret;
12164}
Jeff Johnson04dd8a82012-06-29 20:41:40 -070012165#endif
12166
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012167#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053012168static int __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
12169 struct net_device *dev,
12170 struct cfg80211_update_ft_ies_params *ftie)
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012171{
12172 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12173 hdd_station_ctx_t *pHddStaCtx;
12174
12175 if (NULL == pAdapter)
12176 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080012177 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL", __func__);
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012178 return -ENODEV;
12179 }
12180
12181 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12182
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053012183 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12184 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
12185 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012186 // Added for debug on reception of Re-assoc Req.
12187 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
12188 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080012189 hddLog(LOGE, FL("Called with Ie of length = %zu when not associated"),
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012190 ftie->ie_len);
Arif Hussain6d2a3322013-11-17 19:50:10 -080012191 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012192 }
12193
12194#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
Arif Hussain6d2a3322013-11-17 19:50:10 -080012195 hddLog(LOGE, FL("%s called with Ie of length = %zu"), __func__,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012196 ftie->ie_len);
12197#endif
12198
12199 // Pass the received FT IEs to SME
Gopichand Nakkala356fb102013-03-06 12:34:04 +053012200 sme_SetFTIEs( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
12201 (const u8 *)ftie->ie,
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012202 ftie->ie_len);
12203 return 0;
12204}
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053012205
12206static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
12207 struct net_device *dev,
12208 struct cfg80211_update_ft_ies_params *ftie)
12209{
12210 int ret;
12211
12212 vos_ssr_protect(__func__);
12213 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
12214 vos_ssr_unprotect(__func__);
12215
12216 return ret;
12217}
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070012218#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -070012219
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012220#ifdef FEATURE_WLAN_SCAN_PNO
12221
12222void hdd_cfg80211_sched_scan_done_callback(void *callbackContext,
12223 tSirPrefNetworkFoundInd *pPrefNetworkFoundInd)
12224{
12225 int ret;
12226 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
12227 hdd_context_t *pHddCtx;
12228
Nirav Shah80830bf2013-12-31 16:35:12 +053012229 ENTER();
12230
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012231 if (NULL == pAdapter)
12232 {
Agarwal Ashish971c2882013-10-30 20:11:12 +053012233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012234 "%s: HDD adapter is Null", __func__);
12235 return ;
12236 }
12237
12238 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12239 if (NULL == pHddCtx)
12240 {
12241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12242 "%s: HDD context is Null!!!", __func__);
12243 return ;
12244 }
12245
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012246 spin_lock(&pHddCtx->schedScan_lock);
12247 if (TRUE == pHddCtx->isWiphySuspended)
12248 {
12249 pHddCtx->isSchedScanUpdatePending = TRUE;
12250 spin_unlock(&pHddCtx->schedScan_lock);
12251 hddLog(VOS_TRACE_LEVEL_INFO,
12252 "%s: Update cfg80211 scan database after it resume", __func__);
12253 return ;
12254 }
12255 spin_unlock(&pHddCtx->schedScan_lock);
12256
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012257 ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter);
12258
12259 if (0 > ret)
12260 hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__);
12261
12262 cfg80211_sched_scan_results(pHddCtx->wiphy);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12264 "%s: cfg80211 scan result database updated", __func__);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012265}
12266
12267/*
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012268 * FUNCTION: wlan_hdd_is_pno_allowed
Vinay Krishna Erannacbf75f42014-02-26 17:35:20 +053012269 * Disallow pno if any session is active
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012270 */
12271static eHalStatus wlan_hdd_is_pno_allowed(hdd_adapter_t *pAdapter)
12272{
12273 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
12274 hdd_adapter_t *pTempAdapter = NULL;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012275 hdd_station_ctx_t *pStaCtx;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012276 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12277 int status = 0;
12278 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
12279
Vinay Krishna Erannacbf75f42014-02-26 17:35:20 +053012280 /* The current firmware design does not allow PNO during any
12281 * active sessions. Hence, determine the active sessions
12282 * and return a failure.
12283 */
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012284 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status))
12285 {
12286 pTempAdapter = pAdapterNode->pAdapter;
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012287 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pTempAdapter);
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012288
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012289 if (((WLAN_HDD_INFRA_STATION == pTempAdapter->device_mode)
12290 && (eConnectionState_NotConnected != pStaCtx->conn_info.connState))
12291 || (WLAN_HDD_P2P_CLIENT == pTempAdapter->device_mode)
12292 || (WLAN_HDD_P2P_GO == pTempAdapter->device_mode)
12293 || (WLAN_HDD_SOFTAP == pTempAdapter->device_mode)
12294 )
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012295 {
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012296 return eHAL_STATUS_FAILURE;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012297 }
12298 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
12299 pAdapterNode = pNext;
12300 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012301 return eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012302}
12303
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012304void hdd_cfg80211_sched_scan_start_status_cb(void *callbackContext, VOS_STATUS status)
12305{
12306 hdd_adapter_t *pAdapter = callbackContext;
12307 hdd_context_t *pHddCtx;
12308
12309 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
12310 {
12311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12312 FL("Invalid adapter or adapter has invalid magic"));
12313 return;
12314 }
12315
12316 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12317 if (0 != wlan_hdd_validate_context(pHddCtx))
12318 {
12319 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12320 FL("HDD context is not valid"));
12321 return;
12322 }
12323
12324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12325 FL("PNO enable response status = %d"), status);
12326
12327 pAdapter->pno_req_status = (status == VOS_STATUS_SUCCESS) ? 0 : -EBUSY;
12328 complete(&pAdapter->pno_comp_var);
12329}
12330
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012331/*
Mahesh A Saptasagar6cc38562014-05-23 21:22:17 +053012332 * FUNCTION: __wlan_hdd_cfg80211_sched_scan_start
12333 * Function to enable PNO
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012334 */
Mahesh A Saptasagar6cc38562014-05-23 21:22:17 +053012335static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012336 struct net_device *dev, struct cfg80211_sched_scan_request *request)
12337{
12338 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12339 tpSirPNOScanReq pPnoRequest = NULL;
12340 hdd_context_t *pHddCtx;
12341 tHalHandle hHal;
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +053012342 v_U32_t i, indx, num_ch, tempInterval;
Sushant Kaushikd62d9782014-02-19 15:39:40 +053012343 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
12344 u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012345 v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12346 eHalStatus status = eHAL_STATUS_FAILURE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012347 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012348
12349 if (NULL == pAdapter)
12350 {
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053012351 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012352 "%s: HDD adapter is Null", __func__);
12353 return -ENODEV;
12354 }
12355
12356 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012357 ret = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012358
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012359 if (0 != ret)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012360 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +053012361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12362 "%s: HDD context is not valid", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012363 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012364 }
12365
12366 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12367 if (NULL == hHal)
12368 {
12369 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12370 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012371 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012372 }
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012373
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053012374 ret = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +053012375 if (ret < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053012376 {
12377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12378 "%s: aborting the existing scan is unsuccessfull", __func__);
12379 return -EBUSY;
12380 }
12381
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012382 if (eHAL_STATUS_SUCCESS != wlan_hdd_is_pno_allowed(pAdapter))
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012383 {
Vinay Krishna Erannacbf75f42014-02-26 17:35:20 +053012384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Vinay Krishna Eranna23ffd182013-12-26 19:16:55 +053012385 FL("Cannot handle sched_scan"));
Mahesh A Saptasagar0f7b0372013-11-28 23:23:07 +053012386 return -EBUSY;
12387 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012388
c_hpothu37f21312014-04-09 21:49:54 +053012389 if (TRUE == pHddCtx->isPnoEnable)
12390 {
12391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
12392 FL("already PNO is enabled"));
12393 return -EBUSY;
12394 }
12395 pHddCtx->isPnoEnable = TRUE;
12396
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012397 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
12398 if (NULL == pPnoRequest)
12399 {
12400 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
12401 "%s: vos_mem_malloc failed", __func__);
c_hpothu37f21312014-04-09 21:49:54 +053012402 pHddCtx->isPnoEnable = FALSE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012403 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012404 }
12405
Madan Mohan Koyyalamudic3f04352013-09-26 19:21:48 +053012406 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012407 pPnoRequest->enable = 1; /*Enable PNO */
12408 pPnoRequest->ucNetworksCount = request->n_match_sets;
12409
12410 if (( !pPnoRequest->ucNetworksCount ) ||
12411 ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS ))
12412 {
12413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik1e406c32014-05-09 15:57:52 +053012414 "%s: Network input is not correct %d Max Network supported is %d",
12415 __func__, pPnoRequest->ucNetworksCount,
12416 SIR_PNO_MAX_SUPP_NETWORKS);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012417 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012418 goto error;
12419 }
12420
12421 if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels )
12422 {
12423 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +053012424 "%s: Incorrect number of channels %d",
12425 __func__, request->n_channels);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012426 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012427 goto error;
12428 }
12429
12430 /* Framework provides one set of channels(all)
12431 * common for all saved profile */
12432 if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12433 channels_allowed, &num_channels_allowed))
12434 {
12435 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12436 "%s: failed to get valid channel list", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012437 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012438 goto error;
12439 }
12440 /* Checking each channel against allowed channel list */
12441 num_ch = 0;
Nirav Shah80830bf2013-12-31 16:35:12 +053012442 if (request->n_channels)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012443 {
Nirav Shah80830bf2013-12-31 16:35:12 +053012444 char chList [(request->n_channels*5)+1];
12445 int len;
12446 for (i = 0, len = 0; i < request->n_channels; i++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012447 {
Nirav Shah80830bf2013-12-31 16:35:12 +053012448 for (indx = 0; indx < num_channels_allowed; indx++)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012449 {
Nirav Shah80830bf2013-12-31 16:35:12 +053012450 if (request->channels[i]->hw_value == channels_allowed[indx])
12451 {
12452 valid_ch[num_ch++] = request->channels[i]->hw_value;
12453 len += snprintf(chList+len, 5, "%d ",
12454 request->channels[i]->hw_value);
12455 break ;
12456 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012457 }
12458 }
Nirav Shah80830bf2013-12-31 16:35:12 +053012459 hddLog(VOS_TRACE_LEVEL_INFO,"Channel-List: %s ", chList);
12460 }
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012461
12462 /* Filling per profile params */
12463 for (i = 0; i < pPnoRequest->ucNetworksCount; i++)
12464 {
12465 pPnoRequest->aNetworks[i].ssId.length =
12466 request->match_sets[i].ssid.ssid_len;
12467
12468 if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) ||
12469 ( pPnoRequest->aNetworks[i].ssId.length > 32 ) )
12470 {
12471 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +053012472 "%s: SSID Len %d is not correct for network %d",
12473 __func__, pPnoRequest->aNetworks[i].ssId.length, i);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012474 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012475 goto error;
12476 }
12477
12478 memcpy(pPnoRequest->aNetworks[i].ssId.ssId,
12479 request->match_sets[i].ssid.ssid,
12480 request->match_sets[i].ssid.ssid_len);
Sushant Kaushik1e406c32014-05-09 15:57:52 +053012481 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12482 "%s: SSID of network %d is %s ", __func__,
12483 i, pPnoRequest->aNetworks[i].ssId.ssId);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012484 pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/
12485 pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/
12486 pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/
12487
12488 /*Copying list of valid channel into request */
12489 memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch);
12490 pPnoRequest->aNetworks[i].ucChannelCount = num_ch;
12491
12492 pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value
12493 }
12494
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +053012495 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnson59a121e2013-11-30 09:46:08 -080012496 "request->ie_len = %zu", request->ie_len);
Madan Mohan Koyyalamudia7765d52013-09-18 16:49:56 +053012497 if ((0 < request->ie_len) && (NULL != request->ie))
12498 {
12499 pPnoRequest->us24GProbeTemplateLen = request->ie_len;
12500 memcpy(&pPnoRequest->p24GProbeTemplate, request->ie,
12501 pPnoRequest->us24GProbeTemplateLen);
12502
12503 pPnoRequest->us5GProbeTemplateLen = request->ie_len;
12504 memcpy(&pPnoRequest->p5GProbeTemplate, request->ie,
12505 pPnoRequest->us5GProbeTemplateLen);
12506 }
12507
Madan Mohan Koyyalamudi1d16f462013-08-27 16:25:34 +053012508 /* Driver gets only one time interval which is hardcoded in
12509 * supplicant for 10000ms. Taking power consumption into account 6 timers
12510 * will be used, Timervalue is increased exponentially i.e 10,20,40,
12511 * 80,160,320 secs. And number of scan cycle for each timer
12512 * is configurable through INI param gPNOScanTimerRepeatValue.
12513 * If it is set to 0 only one timer will be used and PNO scan cycle
12514 * will be repeated after each interval specified by supplicant
12515 * till PNO is disabled.
12516 */
12517 if (0 == pHddCtx->cfg_ini->configPNOScanTimerRepeatValue)
12518 pPnoRequest->scanTimers.ucScanTimersCount = HDD_PNO_SCAN_TIMERS_SET_ONE;
12519 else
12520 pPnoRequest->scanTimers.ucScanTimersCount =
12521 HDD_PNO_SCAN_TIMERS_SET_MULTIPLE;
12522
12523 tempInterval = (request->interval)/1000;
12524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12525 "Base scan interval = %d PNOScanTimerRepeatValue = %d",
12526 tempInterval, pHddCtx->cfg_ini->configPNOScanTimerRepeatValue);
12527 for ( i = 0; i < pPnoRequest->scanTimers.ucScanTimersCount; i++)
12528 {
12529 pPnoRequest->scanTimers.aTimerValues[i].uTimerRepeat =
12530 pHddCtx->cfg_ini->configPNOScanTimerRepeatValue;
12531 pPnoRequest->scanTimers.aTimerValues[i].uTimerValue = tempInterval;
12532 tempInterval *= 2;
12533 }
12534 //Repeat last timer until pno disabled.
12535 pPnoRequest->scanTimers.aTimerValues[i-1].uTimerRepeat = 0;
12536
Madan Mohan Koyyalamudid206c7b2013-09-26 22:54:51 +053012537 pPnoRequest->modePNO = SIR_PNO_MODE_IMMEDIATE;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012538
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012539 INIT_COMPLETION(pAdapter->pno_comp_var);
12540 pPnoRequest->statusCallback = hdd_cfg80211_sched_scan_start_status_cb;
12541 pPnoRequest->callbackContext = pAdapter;
12542 pAdapter->pno_req_status = 0;
12543
Nirav Shah80830bf2013-12-31 16:35:12 +053012544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12545 "SessionId %d, enable %d, modePNO %d, ucScanTimersCount %d",
12546 pAdapter->sessionId, pPnoRequest->enable, pPnoRequest->modePNO,
12547 pPnoRequest->scanTimers.ucScanTimersCount);
12548
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012549 status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter),
12550 pPnoRequest, pAdapter->sessionId,
12551 hdd_cfg80211_sched_scan_done_callback, pAdapter);
12552 if (eHAL_STATUS_SUCCESS != status)
12553 {
12554 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Nirav Shah80830bf2013-12-31 16:35:12 +053012555 "%s: Failed to enable PNO", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012556 ret = -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012557 goto error;
12558 }
12559
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012560 ret = wait_for_completion_timeout(
12561 &pAdapter->pno_comp_var,
12562 msecs_to_jiffies(WLAN_WAIT_TIME_PNO));
12563 if (0 >= ret)
12564 {
12565 // Did not receive the response for PNO enable in time.
12566 // Assuming the PNO enable was success.
12567 // Returning error from here, because we timeout, results
12568 // in side effect of Wifi (Wifi Setting) not to work.
12569 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12570 FL("Timed out waiting for PNO to be Enabled"));
12571 ret = 0;
12572 goto error;
12573 }
12574
c_hpothu3c986b22014-07-09 14:45:09 +053012575 vos_mem_free(pPnoRequest);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012576 ret = pAdapter->pno_req_status;
c_hpothu37f21312014-04-09 21:49:54 +053012577 return ret;
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012578
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012579error:
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
12581 FL("PNO scanRequest offloaded ret = %d"), ret);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012582 vos_mem_free(pPnoRequest);
c_hpothu37f21312014-04-09 21:49:54 +053012583 pHddCtx->isPnoEnable = FALSE;
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012584 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012585}
12586
12587/*
Mahesh A Saptasagar6cc38562014-05-23 21:22:17 +053012588 * FUNCTION: wlan_hdd_cfg80211_sched_scan_start
12589 * NL interface to enable PNO
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012590 */
Mahesh A Saptasagar6cc38562014-05-23 21:22:17 +053012591static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
12592 struct net_device *dev, struct cfg80211_sched_scan_request *request)
12593{
12594 int ret;
12595
12596 vos_ssr_protect(__func__);
12597 ret = __wlan_hdd_cfg80211_sched_scan_start(wiphy, dev, request);
12598 vos_ssr_unprotect(__func__);
12599
12600 return ret;
12601}
12602
12603/*
12604 * FUNCTION: __wlan_hdd_cfg80211_sched_scan_stop
12605 * Function to disable PNO
12606 */
12607static int __wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012608 struct net_device *dev)
12609{
12610 eHalStatus status = eHAL_STATUS_FAILURE;
12611 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12612 hdd_context_t *pHddCtx;
12613 tHalHandle hHal;
12614 tpSirPNOScanReq pPnoRequest = NULL;
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012615 int ret = 0;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012616
12617 ENTER();
12618
12619 if (NULL == pAdapter)
12620 {
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053012621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012622 "%s: HDD adapter is Null", __func__);
12623 return -ENODEV;
12624 }
12625
12626 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012627
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012628 if (NULL == pHddCtx)
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012629 {
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +053012630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012631 "%s: HDD context is Null", __func__);
12632 return -ENODEV;
12633 }
12634
12635 /* The return 0 is intentional when isLogpInProgress and
12636 * isLoadUnloadInProgress. We did observe a crash due to a return of
12637 * failure in sched_scan_stop , especially for a case where the unload
12638 * of the happens at the same time. The function __cfg80211_stop_sched_scan
12639 * was clearing rdev->sched_scan_req only when the sched_scan_stop returns
12640 * success. If it returns a failure , then its next invocation due to the
12641 * clean up of the second interface will have the dev pointer corresponding
12642 * to the first one leading to a crash.
12643 */
12644 if (pHddCtx->isLogpInProgress)
12645 {
12646 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12647 "%s: LOGP in Progress. Ignore!!!", __func__);
12648 return ret;
12649 }
12650
Mihir Shete18156292014-03-11 15:38:30 +053012651 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012652 {
12653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12654 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
12655 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012656 }
12657
12658 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12659 if (NULL == hHal)
12660 {
12661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12662 "%s: HAL context is Null!!!", __func__);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012663 return -EINVAL;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012664 }
12665
12666 pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq));
12667 if (NULL == pPnoRequest)
12668 {
12669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
12670 "%s: vos_mem_malloc failed", __func__);
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012671 return -ENOMEM;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012672 }
12673
12674 memset(pPnoRequest, 0, sizeof (tSirPNOScanReq));
12675 pPnoRequest->enable = 0; /* Disable PNO */
12676 pPnoRequest->ucNetworksCount = 0;
12677
12678 status = sme_SetPreferredNetworkList(hHal, pPnoRequest,
12679 pAdapter->sessionId,
12680 NULL, pAdapter);
12681 if (eHAL_STATUS_SUCCESS != status)
12682 {
12683 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12684 "Failed to disabled PNO");
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012685 ret = -EINVAL;
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012686 goto error;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012687 }
c_hpothu37f21312014-04-09 21:49:54 +053012688 pHddCtx->isPnoEnable = FALSE;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012689
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012690error:
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +053012692 FL("PNO scan disabled ret = %d"), ret);
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012693 vos_mem_free(pPnoRequest);
12694
12695 EXIT();
Kamath Vinayakba5313f2013-08-22 15:52:39 +053012696 return ret;
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012697}
12698
Mahesh A Saptasagar6cc38562014-05-23 21:22:17 +053012699/*
12700 * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop
12701 * NL interface to disable PNO
12702 */
12703static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
12704 struct net_device *dev)
12705{
12706 int ret;
12707
12708 vos_ssr_protect(__func__);
12709 ret = __wlan_hdd_cfg80211_sched_scan_stop(wiphy, dev);
12710 vos_ssr_unprotect(__func__);
12711
12712 return ret;
12713}
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053012714#endif /*FEATURE_WLAN_SCAN_PNO*/
12715
12716
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012717#ifdef FEATURE_WLAN_TDLS
Sunil Dutt Undekarieacac6f2014-03-21 14:08:53 +053012718#if TDLS_MGMT_VERSION2
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012719static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
12720 u8 *peer, u8 action_code, u8 dialog_token,
Sunil Dutt Undekarieacac6f2014-03-21 14:08:53 +053012721 u16 status_code, u32 peer_capability, const u8 *buf, size_t len)
12722#else
12723static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
12724 u8 *peer, u8 action_code, u8 dialog_token,
12725 u16 status_code, const u8 *buf, size_t len)
12726#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012727{
12728
12729 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12730 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012731 u8 peerMac[6];
12732 VOS_STATUS status;
Gopichand Nakkala05922802013-03-14 12:23:19 -070012733 int max_sta_failed = 0;
Hoonki Leea34dd892013-02-05 22:56:02 -080012734 int responder;
Hoonki Leed37cbb32013-04-20 00:31:14 -070012735 long rc;
Sunil Dutt Undekarieacac6f2014-03-21 14:08:53 +053012736#if !(TDLS_MGMT_VERSION2)
12737 u32 peer_capability = 0;
12738#endif
Rajesh Chauhana34c6e62014-03-25 16:37:58 +053012739 tANI_U16 numCurrTdlsPeers;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053012740
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053012741 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12742 TRACE_CODE_HDD_CFG80211_TDLS_MGMT,
12743 pAdapter->sessionId, action_code));
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012744 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012745 {
Gopichand Nakkala747461f2013-04-24 19:24:45 +053012746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012747 "Invalid arguments");
12748 return -EINVAL;
12749 }
12750
Sameer Thalappil75ea31a2013-02-21 19:38:16 -080012751 if (pHddCtx->isLogpInProgress)
12752 {
12753 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12754 "%s:LOGP in Progress. Ignore!!!", __func__);
Gopichand Nakkala05922802013-03-14 12:23:19 -070012755 wlan_hdd_tdls_set_link_status(pAdapter, peer, eTDLS_LINK_IDLE);
Sameer Thalappil75ea31a2013-02-21 19:38:16 -080012756 return -EBUSY;
12757 }
12758
Hoonki Lee27511902013-03-14 18:19:06 -070012759 if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012760 {
Hoonki Lee27511902013-03-14 18:19:06 -070012761 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
12762 "%s: TDLS mode is disabled OR not enabled in FW."
12763 MAC_ADDRESS_STR " action %d declined.",
12764 __func__, MAC_ADDR_ARRAY(peer), action_code);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012765 return -ENOTSUPP;
12766 }
Lee Hoonkic1262f22013-01-24 21:59:00 -080012767
Hoonki Lee27511902013-03-14 18:19:06 -070012768 /* other than teardown frame, other mgmt frames are not sent if disabled */
12769 if (SIR_MAC_TDLS_TEARDOWN != action_code)
12770 {
12771 /* if tdls_mode is disabled to respond to peer's request */
12772 if (eTDLS_SUPPORT_DISABLED == pHddCtx->tdls_mode)
12773 {
12774 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
12775 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -070012776 " TDLS mode is disabled. action %d declined.",
12777 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee27511902013-03-14 18:19:06 -070012778
12779 return -ENOTSUPP;
12780 }
Agarwal Ashish4b87f922014-06-18 03:03:21 +053012781
12782 if (vos_max_concurrent_connections_reached())
12783 {
12784 hddLog(VOS_TRACE_LEVEL_INFO, FL("Reached max concurrent connections"));
12785 return -EINVAL;
12786 }
Hoonki Lee27511902013-03-14 18:19:06 -070012787 }
12788
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012789 if (WLAN_IS_TDLS_SETUP_ACTION(action_code))
12790 {
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012791 if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE))
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012792 {
12793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070012794 "%s: " MAC_ADDRESS_STR
Gopichand Nakkala34d1b062013-03-19 15:28:33 -070012795 " TDLS setup is ongoing. action %d declined.",
12796 __func__, MAC_ADDR_ARRAY(peer), action_code);
12797 return -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012798 }
12799 }
12800
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012801 if (SIR_MAC_TDLS_SETUP_REQ == action_code ||
12802 SIR_MAC_TDLS_SETUP_RSP == action_code )
Lee Hoonkic1262f22013-01-24 21:59:00 -080012803 {
Rajesh Chauhana34c6e62014-03-25 16:37:58 +053012804 numCurrTdlsPeers = wlan_hdd_tdlsConnectedPeers(pAdapter);
12805 if (HDD_MAX_NUM_TDLS_STA <= numCurrTdlsPeers)
Lee Hoonkic1262f22013-01-24 21:59:00 -080012806 {
12807 /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
12808 we return error code at 'add_station()'. Hence we have this
12809 check again in addtion to add_station().
12810 Anyway, there is no hard to double-check. */
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012811 if (SIR_MAC_TDLS_SETUP_REQ == action_code)
Lee Hoonkic1262f22013-01-24 21:59:00 -080012812 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070012813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12814 "%s: " MAC_ADDRESS_STR
Rajesh Chauhana34c6e62014-03-25 16:37:58 +053012815 " TDLS Max peer already connected. action (%d) declined. Num of peers (%d), Max allowed (%d).",
12816 __func__, MAC_ADDR_ARRAY(peer), action_code,
12817 numCurrTdlsPeers, HDD_MAX_NUM_TDLS_STA);
Sunil Dutt388ac8f2013-11-28 18:06:52 +053012818 return -EINVAL;
Lee Hoonkic1262f22013-01-24 21:59:00 -080012819 }
12820 else
12821 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012822 /* maximum reached. tweak to send error code to peer and return
12823 error code to supplicant */
Lee Hoonkic1262f22013-01-24 21:59:00 -080012824 status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070012825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12826 "%s: " MAC_ADDRESS_STR
Rajesh Chauhana34c6e62014-03-25 16:37:58 +053012827 " TDLS Max peer already connected, send response status (%d). Num of peers (%d), Max allowed (%d).",
12828 __func__, MAC_ADDR_ARRAY(peer), status_code,
12829 numCurrTdlsPeers, HDD_MAX_NUM_TDLS_STA);
Gopichand Nakkala05922802013-03-14 12:23:19 -070012830 max_sta_failed = -EPERM;
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012831 /* fall through to send setup resp with failure status
12832 code */
Lee Hoonkic1262f22013-01-24 21:59:00 -080012833 }
12834 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012835 else
12836 {
12837 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012838 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -070012839 if (pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012840 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070012841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala34d1b062013-03-19 15:28:33 -070012842 "%s:" MAC_ADDRESS_STR " already connected. action %d declined.",
12843 __func__, MAC_ADDR_ARRAY(peer), action_code);
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012844 return -EPERM;
12845 }
12846 }
Lee Hoonkic1262f22013-01-24 21:59:00 -080012847 }
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012848 vos_mem_copy(peerMac, peer, 6);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012849
Hoonki Lee1090c6a2013-01-16 17:40:54 -080012850#ifdef WLAN_FEATURE_TDLS_DEBUG
12851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Kumar Khandavalli9fb625e2014-03-17 16:07:40 +053012852 "%s: " MAC_ADDRESS_STR " action %d, dialog_token %d status %d, len = %zu",
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070012853 "tdls_mgmt", MAC_ADDR_ARRAY(peer),
12854 action_code, dialog_token, status_code, len);
Hoonki Lee1090c6a2013-01-16 17:40:54 -080012855#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012856
Hoonki Leea34dd892013-02-05 22:56:02 -080012857 /*Except teardown responder will not be used so just make 0*/
12858 responder = 0;
Hoonki Lee11f7dda2013-02-14 16:55:44 -080012859 if (SIR_MAC_TDLS_TEARDOWN == action_code)
Hoonki Leea34dd892013-02-05 22:56:02 -080012860 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -070012861
12862 hddTdlsPeer_t *pTdlsPeer;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012863 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac, TRUE);
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -070012864
12865 if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer))
12866 responder = pTdlsPeer->is_responder;
12867 else
Hoonki Leea34dd892013-02-05 22:56:02 -080012868 {
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -070012869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Kumar Khandavalli9fb625e2014-03-17 16:07:40 +053012870 "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %zu",
Gopichand Nakkala97a65fd2013-04-16 16:59:38 -070012871 __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status,
12872 dialog_token, status_code, len);
12873 return -EPERM;
Hoonki Leea34dd892013-02-05 22:56:02 -080012874 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012875 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012876
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +053012877 /* For explicit trigger of DIS_REQ come out of BMPS for
12878 successfully receiving DIS_RSP from peer. */
Hoonki Lee14621352013-04-16 17:51:19 -070012879 if ((SIR_MAC_TDLS_SETUP_RSP == action_code) ||
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +053012880 (SIR_MAC_TDLS_DIS_RSP == action_code) ||
12881 (SIR_MAC_TDLS_DIS_REQ == action_code))
Hoonki Lee14621352013-04-16 17:51:19 -070012882 {
12883 if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter)))
12884 {
12885 VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +053012886 "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code);
Hoonki Lee14621352013-04-16 17:51:19 -070012887 hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION);
12888 }
Gopichand Nakkala2f1ff152013-07-01 11:27:43 +053012889 if (SIR_MAC_TDLS_DIS_REQ != action_code)
12890 wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED);
Hoonki Lee14621352013-04-16 17:51:19 -070012891 }
12892
Hoonki Lee5305c3a2013-04-29 23:28:59 -070012893 /* make sure doesn't call send_mgmt() while it is pending */
12894 if (TDLS_CTX_MAGIC == pAdapter->mgmtTxCompletionStatus)
12895 {
12896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -080012897 "%s: " MAC_ADDRESS_STR " action %d couldn't sent, as one is pending. return EBUSY",
Hoonki Lee5305c3a2013-04-29 23:28:59 -070012898 __func__, MAC_ADDR_ARRAY(peer), action_code);
12899 return -EBUSY;
12900 }
12901
12902 pAdapter->mgmtTxCompletionStatus = TDLS_CTX_MAGIC;
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012903 INIT_COMPLETION(pAdapter->tdls_mgmt_comp);
12904
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012905 status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
Pradeep Reddy POTTETIca171f82014-03-21 14:17:35 +053012906 peerMac, action_code, dialog_token, status_code, peer_capability, (tANI_U8 *)buf, len, responder);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012907
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012908 if (VOS_STATUS_SUCCESS != status)
12909 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012910 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12911 "%s: sme_SendTdlsMgmtFrame failed!", __func__);
Hoonki Lee5305c3a2013-04-29 23:28:59 -070012912 pAdapter->mgmtTxCompletionStatus = FALSE;
Hoonki Lee14621352013-04-16 17:51:19 -070012913 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +053012914 return -EINVAL;
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012915 }
12916
Hoonki Leed37cbb32013-04-20 00:31:14 -070012917 rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp,
12918 msecs_to_jiffies(WAIT_TIME_TDLS_MGMT));
12919
12920 if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus))
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012921 {
Hoonki Leed37cbb32013-04-20 00:31:14 -070012922 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson0299d0a2013-10-30 12:37:43 -070012923 "%s: Mgmt Tx Completion failed status %ld TxCompletion %u",
Hoonki Leed37cbb32013-04-20 00:31:14 -070012924 __func__, rc, pAdapter->mgmtTxCompletionStatus);
Hoonki Lee5305c3a2013-04-29 23:28:59 -070012925 pAdapter->mgmtTxCompletionStatus = FALSE;
Yue Ma4f55ef32014-01-23 16:45:33 -080012926
12927 if (pHddCtx->isLogpInProgress)
12928 {
12929 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12930 "%s: LOGP in Progress. Ignore!!!", __func__);
12931 return -EAGAIN;
12932 }
12933
Hoonki Leed37cbb32013-04-20 00:31:14 -070012934 wlan_hdd_tdls_check_bmps(pAdapter);
Sunil Dutt388ac8f2013-11-28 18:06:52 +053012935 return -EINVAL;
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012936 }
12937
Gopichand Nakkala05922802013-03-14 12:23:19 -070012938 if (max_sta_failed)
Hoonki Lee14621352013-04-16 17:51:19 -070012939 {
12940 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala05922802013-03-14 12:23:19 -070012941 return max_sta_failed;
Hoonki Lee14621352013-04-16 17:51:19 -070012942 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012943
Hoonki Leea34dd892013-02-05 22:56:02 -080012944 if (SIR_MAC_TDLS_SETUP_RSP == action_code)
12945 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -080012946 wlan_hdd_tdls_set_responder(pAdapter, peerMac, TRUE);
Hoonki Leea34dd892013-02-05 22:56:02 -080012947 }
12948 else if (SIR_MAC_TDLS_SETUP_CNF == action_code)
12949 {
Gopichand Nakkala4327a152013-03-04 23:22:42 -080012950 wlan_hdd_tdls_set_responder(pAdapter, peerMac, FALSE);
Hoonki Leea34dd892013-02-05 22:56:02 -080012951 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012952
12953 return 0;
12954}
12955
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053012956static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012957 u8 *peer, enum nl80211_tdls_operation oper)
12958{
12959 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12960 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053012961 int status;
Hoonki Lee5305c3a2013-04-29 23:28:59 -070012962 hddTdlsPeer_t *pTdlsPeer;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053012963
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053012964 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
12965 TRACE_CODE_HDD_CFG80211_TDLS_OPER,
12966 pAdapter->sessionId, oper));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053012967 if ( NULL == peer )
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012968 {
Gopichand Nakkalab977a972013-02-18 19:15:09 -080012969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -070012970 "%s: Invalid arguments", __func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012971 return -EINVAL;
12972 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -080012973
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053012974 status = wlan_hdd_validate_context(pHddCtx);
12975
12976 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -080012977 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053012978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12979 "%s: HDD context is not valid", __func__);
12980 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -080012981 }
12982
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012983
12984 if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
Hoonki Lee1090c6a2013-01-16 17:40:54 -080012985 FALSE == sme_IsFeatureSupportedByFW(TDLS))
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012986 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -080012987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Chilam Ngc4244af2013-04-01 15:37:32 -070012988 "TDLS Disabled in INI OR not enabled in FW. "
12989 "Cannot process TDLS commands");
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012990 return -ENOTSUPP;
12991 }
12992
12993 switch (oper) {
12994 case NL80211_TDLS_ENABLE_LINK:
12995 {
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012996 VOS_STATUS status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053012997 long ret;
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053012998 tCsrTdlsLinkEstablishParams tdlsLinkEstablishParams;
Mohit Khanna698ba2a2012-12-04 15:08:18 -080012999
Sunil Dutt41de4e22013-11-14 18:09:02 +053013000 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
13001
13002 if ( NULL == pTdlsPeer ) {
13003 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
13004 " (oper %d) not exsting. ignored",
13005 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
13006 return -EINVAL;
13007 }
13008
13009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13010 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
13011 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
13012 "NL80211_TDLS_ENABLE_LINK");
13013
Gopichand Nakkala2f4a2822013-04-17 11:22:01 -070013014 if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
13015 {
13016 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u "
13017 MAC_ADDRESS_STR " failed",
13018 __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer));
13019 return -EINVAL;
13020 }
13021
Hoonki Lee5305c3a2013-04-29 23:28:59 -070013022 if (eTDLS_LINK_CONNECTED != pTdlsPeer->link_status)
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070013023 {
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053013024 if (IS_ADVANCE_TDLS_ENABLE) {
Gopichand Nakkala24be5312013-07-02 16:47:12 +053013025
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053013026 if (0 != wlan_hdd_tdls_get_link_establish_params(
13027 pAdapter, peer,&tdlsLinkEstablishParams)) {
13028 return -EINVAL;
13029 }
13030 INIT_COMPLETION(pAdapter->tdls_link_establish_req_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053013031
Madan Mohan Koyyalamudice419872013-09-13 19:36:52 +053013032 sme_SendTdlsLinkEstablishParams(WLAN_HDD_GET_HAL_CTX(pAdapter),
13033 pAdapter->sessionId, peer, &tdlsLinkEstablishParams);
13034 /* Send TDLS peer UAPSD capabilities to the firmware and
13035 * register with the TL on after the response for this operation
13036 * is received .
13037 */
13038 ret = wait_for_completion_interruptible_timeout(
13039 &pAdapter->tdls_link_establish_req_comp,
13040 msecs_to_jiffies(WAIT_TIME_TDLS_LINK_ESTABLISH_REQ));
13041 if (ret <= 0)
13042 {
13043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13044 "%s: Link Establish Request Faled Status %ld",
13045 __func__, ret);
13046 return -EINVAL;
13047 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053013048 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -070013049 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED);
Gopichand Nakkala471708b2013-06-04 20:03:01 +053013050 /* Mark TDLS client Authenticated .*/
13051 status = WLANTL_ChangeSTAState( pHddCtx->pvosContext,
13052 pTdlsPeer->staId,
13053 WLANTL_STA_AUTHENTICATED);
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -070013054 if (VOS_STATUS_SUCCESS == status)
13055 {
Hoonki Lee14621352013-04-16 17:51:19 -070013056 if (pTdlsPeer->is_responder == 0)
13057 {
13058 v_U8_t staId = (v_U8_t)pTdlsPeer->staId;
13059
13060 wlan_hdd_tdls_timer_restart(pAdapter,
13061 &pTdlsPeer->initiatorWaitTimeoutTimer,
13062 WAIT_TIME_TDLS_INITIATOR);
13063 /* suspend initiator TX until it receives direct packet from the
13064 reponder or WAIT_TIME_TDLS_INITIATOR timer expires */
13065 WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
13066 &staId, NULL);
13067 }
Gopichand Nakkalaccd3a382013-03-19 13:56:10 -070013068 wlan_hdd_tdls_increment_peer_count(pAdapter);
13069 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070013070 wlan_hdd_tdls_check_bmps(pAdapter);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053013071
13072 /* Update TL about the UAPSD masks , to route the packets to firmware */
Gopichand Nakkala574f6d12013-06-27 19:38:43 +053013073 if ((TRUE == pHddCtx->cfg_ini->fEnableTDLSBufferSta)
13074 || pHddCtx->cfg_ini->fTDLSUapsdMask )
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053013075 {
Gopichand Nakkala574f6d12013-06-27 19:38:43 +053013076 int ac;
13077 uint8 ucAc[4] = { WLANTL_AC_VO,
13078 WLANTL_AC_VI,
13079 WLANTL_AC_BK,
13080 WLANTL_AC_BE };
13081 uint8 tlTid[4] = { 7, 5, 2, 3 } ;
13082 for(ac=0; ac < 4; ac++)
13083 {
13084 status = WLANTL_EnableUAPSDForAC( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
13085 pTdlsPeer->staId, ucAc[ac],
13086 tlTid[ac], tlTid[ac], 0, 0,
13087 WLANTL_BI_DIR );
13088 }
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +053013089 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070013090 }
13091
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013092 }
13093 break;
13094 case NL80211_TDLS_DISABLE_LINK:
Lee Hoonkic1262f22013-01-24 21:59:00 -080013095 {
Sunil Dutt41de4e22013-11-14 18:09:02 +053013096 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
13097
13098 if ( NULL == pTdlsPeer ) {
13099 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR
13100 " (oper %d) not exsting. ignored",
13101 __func__, MAC_ADDR_ARRAY(peer), (int)oper);
13102 return -EINVAL;
13103 }
13104
13105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13106 "%s: " MAC_ADDRESS_STR " link_status %d (%s) ", "tdls_oper",
13107 MAC_ADDR_ARRAY(peer), pTdlsPeer->link_status,
13108 "NL80211_TDLS_DISABLE_LINK");
13109
Hoonki Lee5305c3a2013-04-29 23:28:59 -070013110 if(TDLS_STA_INDEX_VALID(pTdlsPeer->staId))
Lee Hoonkic1262f22013-01-24 21:59:00 -080013111 {
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -070013112 long status;
13113
13114 INIT_COMPLETION(pAdapter->tdls_del_station_comp);
13115
Lee Hoonkic1262f22013-01-24 21:59:00 -080013116 sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
13117 pAdapter->sessionId, peer );
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -070013118
13119 status = wait_for_completion_interruptible_timeout(&pAdapter->tdls_del_station_comp,
13120 msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
13121 if (status <= 0)
13122 {
Hoonki Lee5305c3a2013-04-29 23:28:59 -070013123 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -070013124 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13125 "%s: Del station failed status %ld",
13126 __func__, status);
13127 return -EPERM;
13128 }
Hoonki Lee5305c3a2013-04-29 23:28:59 -070013129 wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_IDLE);
Lee Hoonkic1262f22013-01-24 21:59:00 -080013130 }
13131 else
13132 {
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070013133 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13134 "%s: TDLS Peer Station doesn't exist.", __func__);
Lee Hoonkic1262f22013-01-24 21:59:00 -080013135 }
Lee Hoonkic1262f22013-01-24 21:59:00 -080013136 }
Gopichand Nakkalac87400e2013-03-13 18:51:00 -070013137 break;
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013138 case NL80211_TDLS_TEARDOWN:
Sunil Dutt41de4e22013-11-14 18:09:02 +053013139 {
13140 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13141 " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR,
13142 __func__, MAC_ADDR_ARRAY(peer));
13143
13144 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
13145 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
13146
13147 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13148 " %s TDLS External control and Implicit Trigger not enabled ",
13149 __func__);
13150 return -ENOTSUPP;
13151 }
13152
Sunil Dutt41de4e22013-11-14 18:09:02 +053013153
13154 pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer, TRUE);
13155
13156 if ( NULL == pTdlsPeer ) {
13157 hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR
13158 " peer not exsting",
13159 __func__, MAC_ADDR_ARRAY(peer));
Naresh Jayaram937abdf2013-11-26 19:50:25 +053013160 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +053013161 }
13162 else {
13163 wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer,
13164 eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
13165 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +053013166
13167 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, FALSE) )
13168 return -EINVAL;
Sunil Dutt41de4e22013-11-14 18:09:02 +053013169 break;
13170 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013171 case NL80211_TDLS_SETUP:
Sunil Dutt41de4e22013-11-14 18:09:02 +053013172 {
Naresh Jayaramdb4514b2013-11-25 18:08:10 +053013173 hddTdlsPeer_t *pTdlsPeer;
Sunil Dutt41de4e22013-11-14 18:09:02 +053013174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13175 " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR,
13176 __func__, MAC_ADDR_ARRAY(peer));
13177
13178 if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) ||
13179 (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) {
13180
13181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13182 " %s TDLS External control and Implicit Trigger not enabled ",
13183 __func__);
13184 return -ENOTSUPP;
13185 }
13186
Naresh Jayaramdb4514b2013-11-25 18:08:10 +053013187 /* To cater the requirement of establishing the TDLS link
13188 * irrespective of the data traffic , get an entry of TDLS peer.
13189 */
13190 pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer);
13191 if (pTdlsPeer == NULL) {
13192 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13193 "%s: peer " MAC_ADDRESS_STR " not existing",
13194 __func__, MAC_ADDR_ARRAY(peer));
13195 return -EINVAL;
13196 }
Naresh Jayaram937abdf2013-11-26 19:50:25 +053013197
13198 if ( 0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, TRUE) ) {
13199
13200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13201 " %s TDLS Add Force Peer Failed",
13202 __func__);
13203 return -EINVAL;
13204 }
Naresh Jayaramdb4514b2013-11-25 18:08:10 +053013205 break;
Sunil Dutt41de4e22013-11-14 18:09:02 +053013206 }
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013207 case NL80211_TDLS_DISCOVERY_REQ:
13208 /* We don't support in-driver setup/teardown/discovery */
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
13210 "%s: We don't support in-driver setup/teardown/discovery "
13211 ,__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013212 return -ENOTSUPP;
13213 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013214 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13215 "%s: unsupported event",__func__);
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013216 return -ENOTSUPP;
13217 }
13218 return 0;
13219}
Chilam NG571c65a2013-01-19 12:27:36 +053013220
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013221static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
13222 u8 *peer, enum nl80211_tdls_operation oper)
13223{
13224 int ret;
13225
13226 vos_ssr_protect(__func__);
13227 ret = __wlan_hdd_cfg80211_tdls_oper(wiphy, dev, peer, oper);
13228 vos_ssr_unprotect(__func__);
13229
13230 return ret;
13231}
13232
Chilam NG571c65a2013-01-19 12:27:36 +053013233int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
13234 struct net_device *dev, u8 *peer)
13235{
Arif Hussaina7c8e412013-11-20 11:06:42 -080013236 hddLog(VOS_TRACE_LEVEL_INFO,
13237 "tdls send discover req: "MAC_ADDRESS_STR,
13238 MAC_ADDR_ARRAY(peer));
Chilam NG571c65a2013-01-19 12:27:36 +053013239
Sunil Dutt Undekarieacac6f2014-03-21 14:08:53 +053013240#if TDLS_MGMT_VERSION2
13241 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
13242 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, 0, NULL, 0);
13243#else
Chilam NG571c65a2013-01-19 12:27:36 +053013244 return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
13245 WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
Sunil Dutt Undekarieacac6f2014-03-21 14:08:53 +053013246#endif
Chilam NG571c65a2013-01-19 12:27:36 +053013247}
Mohit Khanna698ba2a2012-12-04 15:08:18 -080013248#endif
13249
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013250#ifdef WLAN_FEATURE_GTK_OFFLOAD
13251/*
13252 * FUNCTION: wlan_hdd_cfg80211_update_replayCounterCallback
13253 * Callback rountine called upon receiving response for
13254 * get offload info
13255 */
13256void wlan_hdd_cfg80211_update_replayCounterCallback(void *callbackContext,
13257 tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
13258{
13259
13260 hdd_adapter_t *pAdapter = (hdd_adapter_t *)callbackContext;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013261 tANI_U8 tempReplayCounter[8];
13262 hdd_station_ctx_t *pHddStaCtx;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013263
13264 ENTER();
13265
13266 if (NULL == pAdapter)
13267 {
Agarwal Ashish971c2882013-10-30 20:11:12 +053013268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013269 "%s: HDD adapter is Null", __func__);
13270 return ;
13271 }
13272
13273 if (NULL == pGtkOffloadGetInfoRsp)
13274 {
13275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13276 "%s: pGtkOffloadGetInfoRsp is Null", __func__);
13277 return ;
13278 }
13279
13280 if (VOS_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus)
13281 {
13282 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13283 "%s: wlan Failed to get replay counter value",
13284 __func__);
13285 return ;
13286 }
13287
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013288 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13289 /* Update replay counter */
13290 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13291 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13292
13293 {
13294 /* changing from little to big endian since supplicant
13295 * works on big endian format
13296 */
13297 int i;
13298 tANI_U8 *p = (tANI_U8 *)&pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13299
13300 for (i = 0; i < 8; i++)
13301 {
13302 tempReplayCounter[7-i] = (tANI_U8)p[i];
13303 }
13304 }
13305
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013306 /* Update replay counter to NL */
13307 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013308 tempReplayCounter, GFP_KERNEL);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013309}
13310
13311/*
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013312 * FUNCTION: __wlan_hdd_cfg80211_set_rekey_data
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013313 * This function is used to offload GTK rekeying job to the firmware.
13314 */
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013315int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013316 struct cfg80211_gtk_rekey_data *data)
13317{
13318 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13319 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13320 hdd_station_ctx_t *pHddStaCtx;
13321 tHalHandle hHal;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053013322 int result;
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013323 tSirGtkOffloadParams hddGtkOffloadReqParams;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013324 eHalStatus status = eHAL_STATUS_FAILURE;
13325
13326 ENTER();
13327
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053013328
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013329 if (NULL == pAdapter)
13330 {
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +053013331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013332 "%s: HDD adapter is Null", __func__);
13333 return -ENODEV;
13334 }
13335
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053013336 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
13337 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13338 pAdapter->sessionId, pAdapter->device_mode));
13339
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053013340 result = wlan_hdd_validate_context(pHddCtx);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013341
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053013342 if (0 != result)
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013343 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053013344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13345 "%s: HDD context is not valid", __func__);
13346 return result;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013347 }
13348
13349 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13350 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13351 if (NULL == hHal)
13352 {
13353 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13354 "%s: HAL context is Null!!!", __func__);
13355 return -EAGAIN;
13356 }
13357
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013358 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13359 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck, NL80211_KCK_LEN);
13360 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek, NL80211_KEK_LEN);
13361 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId, &pHddStaCtx->conn_info.bssId,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013362 WNI_CFG_BSSID_LEN);
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013363 {
13364 /* changing from big to little endian since driver
13365 * works on little endian format
13366 */
13367 tANI_U8 *p =
13368 (tANI_U8 *)&pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter;
13369 int i;
13370
13371 for (i = 0; i < 8; i++)
13372 {
13373 p[7-i] = data->replay_ctr[i];
13374 }
13375 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013376
13377 if (TRUE == pHddCtx->hdd_wlan_suspended)
13378 {
13379 /* if wlan is suspended, enable GTK offload directly from here */
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013380 memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams,
13381 sizeof (tSirGtkOffloadParams));
13382 status = sme_SetGTKOffload(hHal, &hddGtkOffloadReqParams,
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013383 pAdapter->sessionId);
13384
13385 if (eHAL_STATUS_SUCCESS != status)
13386 {
13387 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13388 "%s: sme_SetGTKOffload failed, returned %d",
13389 __func__, status);
13390 return status;
13391 }
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013392 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13393 "%s: sme_SetGTKOffload successfull", __func__);
13394 }
13395 else
13396 {
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13398 "%s: wlan not suspended GTKOffload request is stored",
13399 __func__);
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013400 }
Gopichand Nakkalad36ee622013-05-07 14:13:27 +053013401
13402 return eHAL_STATUS_SUCCESS;
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013403}
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053013404
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013405int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
13406 struct cfg80211_gtk_rekey_data *data)
13407{
13408 int ret;
13409
13410 vos_ssr_protect(__func__);
13411 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
13412 vos_ssr_unprotect(__func__);
13413
13414 return ret;
13415}
13416#endif /*WLAN_FEATURE_GTK_OFFLOAD*/
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +053013417/*
13418 * FUNCTION: wlan_hdd_cfg80211_set_mac_acl
13419 * This function is used to set access control policy
13420 */
13421static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
13422 struct net_device *dev, const struct cfg80211_acl_data *params)
13423{
13424 int i;
13425 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13426 hdd_hostapd_state_t *pHostapdState;
13427 tsap_Config_t *pConfig;
13428 v_CONTEXT_t pVosContext = NULL;
13429 hdd_context_t *pHddCtx;
13430 int status;
13431
13432 ENTER();
13433
13434 if (NULL == pAdapter)
13435 {
13436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13437 "%s: HDD adapter is Null", __func__);
13438 return -ENODEV;
13439 }
13440
13441 if (NULL == params)
13442 {
13443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13444 "%s: params is Null", __func__);
13445 return -EINVAL;
13446 }
13447
13448 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13449 status = wlan_hdd_validate_context(pHddCtx);
13450
13451 if (0 != status)
13452 {
13453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13454 "%s: HDD context is not valid", __func__);
13455 return status;
13456 }
13457
13458 pVosContext = pHddCtx->pvosContext;
13459 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13460
13461 if (NULL == pHostapdState)
13462 {
13463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13464 "%s: pHostapdState is Null", __func__);
13465 return -EINVAL;
13466 }
13467
13468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d"
13469 "no acl entries = %d", params->acl_policy, params->n_acl_entries);
13470
13471 if (WLAN_HDD_SOFTAP == pAdapter->device_mode)
13472 {
13473 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
13474
13475 /* default value */
13476 pConfig->num_accept_mac = 0;
13477 pConfig->num_deny_mac = 0;
13478
13479 /**
13480 * access control policy
13481 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
13482 * listed in hostapd.deny file.
13483 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
13484 * listed in hostapd.accept file.
13485 */
13486 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy)
13487 {
13488 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
13489 }
13490 else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy)
13491 {
13492 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
13493 }
13494 else
13495 {
13496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13497 "%s:Acl Policy : %d is not supported",
13498 __func__, params->acl_policy);
13499 return -ENOTSUPP;
13500 }
13501
13502 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl)
13503 {
13504 pConfig->num_accept_mac = params->n_acl_entries;
13505 for (i = 0; i < params->n_acl_entries; i++)
13506 {
13507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13508 "** Add ACL MAC entry %i in WhiletList :"
13509 MAC_ADDRESS_STR, i,
13510 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
13511
13512 vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr,
13513 sizeof(qcmacaddr));
13514 }
13515 }
13516 else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl)
13517 {
13518 pConfig->num_deny_mac = params->n_acl_entries;
13519 for (i = 0; i < params->n_acl_entries; i++)
13520 {
13521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13522 "** Add ACL MAC entry %i in BlackList :"
13523 MAC_ADDRESS_STR, i,
13524 MAC_ADDR_ARRAY(params->mac_addrs[i].addr));
13525
13526 vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr,
13527 sizeof(qcmacaddr));
13528 }
13529 }
13530
13531 if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig))
13532 {
13533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13534 "%s: SAP Set Mac Acl fail", __func__);
13535 return -EINVAL;
13536 }
13537 }
13538 else
13539 {
13540 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +053013541 "%s: Invalid device_mode = %s (%d)",
13542 __func__, hdd_device_modetoString(pAdapter->device_mode),
13543 pAdapter->device_mode);
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +053013544 return -EINVAL;
13545 }
13546
13547 return 0;
13548}
13549
Leo Chang9056f462013-08-01 19:21:11 -070013550#ifdef WLAN_NL80211_TESTMODE
13551#ifdef FEATURE_WLAN_LPHB
Leo Changd9df8aa2013-09-26 13:32:26 -070013552void wlan_hdd_cfg80211_lphb_ind_handler
Leo Chang9056f462013-08-01 19:21:11 -070013553(
13554 void *pAdapter,
13555 void *indCont
13556)
13557{
Leo Changd9df8aa2013-09-26 13:32:26 -070013558 tSirLPHBInd *lphbInd;
13559 struct sk_buff *skb;
c_hpothu73f35e62014-04-18 13:40:08 +053013560 hdd_context_t *pHddCtxt;
Leo Chang9056f462013-08-01 19:21:11 -070013561
13562 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -070013563 "LPHB indication arrived");
Leo Chang9056f462013-08-01 19:21:11 -070013564
c_hpothu73f35e62014-04-18 13:40:08 +053013565 if (pAdapter == NULL)
13566 {
13567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13568 "%s: pAdapter is NULL\n",__func__);
13569 return;
13570 }
13571
Leo Chang9056f462013-08-01 19:21:11 -070013572 if (NULL == indCont)
13573 {
13574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Leo Changd9df8aa2013-09-26 13:32:26 -070013575 "LPHB IND, invalid argument");
Leo Chang9056f462013-08-01 19:21:11 -070013576 return;
13577 }
13578
c_hpothu73f35e62014-04-18 13:40:08 +053013579 pHddCtxt = (hdd_context_t *)pAdapter;
Leo Changd9df8aa2013-09-26 13:32:26 -070013580 lphbInd = (tSirLPHBInd *)indCont;
Leo Chang9056f462013-08-01 19:21:11 -070013581 skb = cfg80211_testmode_alloc_event_skb(
c_hpothu73f35e62014-04-18 13:40:08 +053013582 pHddCtxt->wiphy,
Leo Changd9df8aa2013-09-26 13:32:26 -070013583 sizeof(tSirLPHBInd),
Leo Chang9056f462013-08-01 19:21:11 -070013584 GFP_ATOMIC);
13585 if (!skb)
13586 {
13587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13588 "LPHB timeout, NL buffer alloc fail");
13589 return;
13590 }
13591
Leo Changac3ba772013-10-07 09:47:04 -070013592 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB))
Leo Changd9df8aa2013-09-26 13:32:26 -070013593 {
13594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13595 "WLAN_HDD_TM_ATTR_CMD put fail");
13596 goto nla_put_failure;
13597 }
Leo Changac3ba772013-10-07 09:47:04 -070013598 if(nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType))
Leo Changd9df8aa2013-09-26 13:32:26 -070013599 {
13600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13601 "WLAN_HDD_TM_ATTR_TYPE put fail");
13602 goto nla_put_failure;
13603 }
Leo Changac3ba772013-10-07 09:47:04 -070013604 if(nla_put(skb, WLAN_HDD_TM_ATTR_DATA,
Leo Changd9df8aa2013-09-26 13:32:26 -070013605 sizeof(tSirLPHBInd), lphbInd))
13606 {
13607 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13608 "WLAN_HDD_TM_ATTR_DATA put fail");
13609 goto nla_put_failure;
13610 }
Leo Chang9056f462013-08-01 19:21:11 -070013611 cfg80211_testmode_event(skb, GFP_ATOMIC);
13612 return;
13613
13614nla_put_failure:
13615 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13616 "NLA Put fail");
13617 kfree_skb(skb);
13618
13619 return;
13620}
13621#endif /* FEATURE_WLAN_LPHB */
13622
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013623static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
Leo Chang9056f462013-08-01 19:21:11 -070013624{
13625 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
13626 int err = 0;
13627#ifdef FEATURE_WLAN_LPHB
13628 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Leo Changd9df8aa2013-09-26 13:32:26 -070013629 eHalStatus smeStatus;
Leo Chang9056f462013-08-01 19:21:11 -070013630#endif /* FEATURE_WLAN_LPHB */
13631
13632 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data, len, wlan_hdd_tm_policy);
13633 if (err)
13634 {
13635 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13636 "%s Testmode INV ATTR", __func__);
13637 return err;
13638 }
13639
13640 if (!tb[WLAN_HDD_TM_ATTR_CMD])
13641 {
13642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13643 "%s Testmode INV CMD", __func__);
13644 return -EINVAL;
13645 }
13646
13647 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]))
13648 {
13649#ifdef FEATURE_WLAN_LPHB
13650 /* Low Power Heartbeat configuration request */
13651 case WLAN_HDD_TM_CMD_WLAN_HB:
13652 {
13653 int buf_len;
13654 void *buf;
13655 tSirLPHBReq *hb_params = NULL;
Amar Singhal05852702014-02-04 14:40:00 -080013656 tSirLPHBReq *hb_params_temp = NULL;
Leo Chang9056f462013-08-01 19:21:11 -070013657
13658 if (!tb[WLAN_HDD_TM_ATTR_DATA])
13659 {
13660 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13661 "%s Testmode INV DATA", __func__);
13662 return -EINVAL;
13663 }
13664
13665 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
13666 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
Amar Singhal05852702014-02-04 14:40:00 -080013667
13668 hb_params_temp =(tSirLPHBReq *)buf;
13669 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID) &&
13670 (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0))
13671 return -EINVAL;
13672
Leo Chang9056f462013-08-01 19:21:11 -070013673 hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq));
13674 if (NULL == hb_params)
13675 {
13676 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13677 "%s Request Buffer Alloc Fail", __func__);
13678 return -EINVAL;
13679 }
13680
13681 vos_mem_copy(hb_params, buf, buf_len);
Leo Changd9df8aa2013-09-26 13:32:26 -070013682 smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal),
13683 hb_params,
13684 wlan_hdd_cfg80211_lphb_ind_handler);
13685 if (eHAL_STATUS_SUCCESS != smeStatus)
Leo Chang9056f462013-08-01 19:21:11 -070013686 {
Leo Changd9df8aa2013-09-26 13:32:26 -070013687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13688 "LPHB Config Fail, disable");
Leo Chang9056f462013-08-01 19:21:11 -070013689 vos_mem_free(hb_params);
13690 }
Leo Chang9056f462013-08-01 19:21:11 -070013691 return 0;
13692 }
13693#endif /* FEATURE_WLAN_LPHB */
13694 default:
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013695 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13696 "%s: unsupported event",__func__);
Leo Chang9056f462013-08-01 19:21:11 -070013697 return -EOPNOTSUPP;
13698 }
13699
13700 return err;
13701}
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013702
13703static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
13704{
13705 int ret;
13706
13707 vos_ssr_protect(__func__);
13708 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
13709 vos_ssr_unprotect(__func__);
13710
13711 return ret;
13712}
Leo Chang9056f462013-08-01 19:21:11 -070013713#endif /* CONFIG_NL80211_TESTMODE */
13714
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013715static int __wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013716 struct net_device *dev,
13717 int idx, struct survey_info *survey)
13718{
13719 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13720 hdd_context_t *pHddCtx;
Mihir Sheted9072e02013-08-21 17:02:29 +053013721 hdd_station_ctx_t *pHddStaCtx;
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013722 tHalHandle halHandle;
Mihir Sheted9072e02013-08-21 17:02:29 +053013723 v_U32_t channel = 0, freq = 0; /* Initialization Required */
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013724 v_S7_t snr,rssi;
13725 int status, i, j, filled = 0;
13726
13727 ENTER();
13728
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013729 if (NULL == pAdapter)
13730 {
13731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13732 "%s: HDD adapter is Null", __func__);
13733 return -ENODEV;
13734 }
13735
13736 if (NULL == wiphy)
13737 {
13738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13739 "%s: wiphy is Null", __func__);
13740 return -ENODEV;
13741 }
13742
13743 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13744 status = wlan_hdd_validate_context(pHddCtx);
13745
13746 if (0 != status)
13747 {
13748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13749 "%s: HDD context is not valid", __func__);
13750 return status;
13751 }
13752
Mihir Sheted9072e02013-08-21 17:02:29 +053013753 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13754
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013755 if (0 == pHddCtx->cfg_ini->fEnableSNRMonitoring ||
Mihir Sheted9072e02013-08-21 17:02:29 +053013756 0 != pAdapter->survey_idx ||
13757 eConnectionState_Associated != pHddStaCtx->conn_info.connState)
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013758 {
13759 /* The survey dump ops when implemented completely is expected to
13760 * return a survey of all channels and the ops is called by the
13761 * kernel with incremental values of the argument 'idx' till it
13762 * returns -ENONET. But we can only support the survey for the
13763 * operating channel for now. survey_idx is used to track
13764 * that the ops is called only once and then return -ENONET for
13765 * the next iteration
13766 */
13767 pAdapter->survey_idx = 0;
13768 return -ENONET;
13769 }
13770
13771 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13772
13773 wlan_hdd_get_snr(pAdapter, &snr);
13774 wlan_hdd_get_rssi(pAdapter, &rssi);
13775
13776 sme_GetOperationChannel(halHandle, &channel, pAdapter->sessionId);
13777 hdd_wlan_get_freq(channel, &freq);
13778
13779
13780 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
13781 {
13782 if (NULL == wiphy->bands[i])
13783 {
13784 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
13785 "%s: wiphy->bands[i] is NULL, i = %d", __func__, i);
13786 continue;
13787 }
13788
13789 for (j = 0; j < wiphy->bands[i]->n_channels; j++)
13790 {
13791 struct ieee80211_supported_band *band = wiphy->bands[i];
13792
13793 if (band->channels[j].center_freq == (v_U16_t)freq)
13794 {
13795 survey->channel = &band->channels[j];
13796 /* The Rx BDs contain SNR values in dB for the received frames
13797 * while the supplicant expects noise. So we calculate and
13798 * return the value of noise (dBm)
13799 * SNR (dB) = RSSI (dBm) - NOISE (dBm)
13800 */
13801 survey->noise = rssi - snr;
13802 survey->filled = SURVEY_INFO_NOISE_DBM;
13803 filled = 1;
13804 }
13805 }
13806 }
13807
13808 if (filled)
13809 pAdapter->survey_idx = 1;
13810 else
13811 {
13812 pAdapter->survey_idx = 0;
13813 return -ENONET;
13814 }
13815
13816 return 0;
13817}
13818
Mahesh A Saptasagar27574072014-06-17 13:39:04 +053013819static int wlan_hdd_cfg80211_dump_survey(struct wiphy *wiphy,
13820 struct net_device *dev,
13821 int idx, struct survey_info *survey)
13822{
13823 int ret;
13824
13825 vos_ssr_protect(__func__);
13826 ret = __wlan_hdd_cfg80211_dump_survey(wiphy, dev, idx, survey);
13827 vos_ssr_unprotect(__func__);
13828
13829 return ret;
13830}
13831
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013832/*
Mahesh A Saptasagarbcc5b662014-06-02 21:46:23 +053013833 * FUNCTION: __wlan_hdd_cfg80211_resume_wlan
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013834 * this is called when cfg80211 driver resume
13835 * driver updates latest sched_scan scan result(if any) to cfg80211 database
13836 */
Mahesh A Saptasagarbcc5b662014-06-02 21:46:23 +053013837int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013838{
13839 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13840 hdd_adapter_t *pAdapter;
13841 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13842 VOS_STATUS status = VOS_STATUS_SUCCESS;
13843
13844 ENTER();
13845
13846 if ( NULL == pHddCtx )
13847 {
13848 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13849 "%s: HddCtx validation failed", __func__);
13850 return 0;
13851 }
13852
13853 if (pHddCtx->isLogpInProgress)
13854 {
13855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13856 "%s: LOGP in Progress. Ignore!!!", __func__);
13857 return 0;
13858 }
13859
Mihir Shete18156292014-03-11 15:38:30 +053013860 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013861 {
13862 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13863 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
13864 return 0;
13865 }
13866
13867 spin_lock(&pHddCtx->schedScan_lock);
13868 pHddCtx->isWiphySuspended = FALSE;
13869 if (TRUE != pHddCtx->isSchedScanUpdatePending)
13870 {
13871 spin_unlock(&pHddCtx->schedScan_lock);
13872 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13873 "%s: Return resume is not due to PNO indication", __func__);
13874 return 0;
13875 }
13876 // Reset flag to avoid updatating cfg80211 data old results again
13877 pHddCtx->isSchedScanUpdatePending = FALSE;
13878 spin_unlock(&pHddCtx->schedScan_lock);
13879
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +053013880
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013881 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13882
13883 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
13884 {
13885 pAdapter = pAdapterNode->pAdapter;
13886 if ( (NULL != pAdapter) &&
13887 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) )
13888 {
13889 if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter))
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +053013890 {
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013891 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
13892 "%s: NO SCAN result", __func__);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +053013893 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013894 else
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +053013895 {
13896 /* Acquire wakelock to handle the case where APP's tries to
13897 * suspend immediately after updating the scan results. Whis
13898 * results in app's is in suspended state and not able to
13899 * process the connect request to AP
13900 */
13901 hdd_prevent_suspend_timeout(2000);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013902 cfg80211_sched_scan_results(pHddCtx->wiphy);
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +053013903 }
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013904
13905 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13906 "%s : cfg80211 scan result database updated", __func__);
13907
13908 return 0;
13909
13910 }
13911 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13912 pAdapterNode = pNext;
13913 }
13914
13915 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13916 "%s: Failed to find Adapter", __func__);
13917 return 0;
13918}
13919
Mahesh A Saptasagarbcc5b662014-06-02 21:46:23 +053013920int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
13921{
13922 int ret;
13923
13924 vos_ssr_protect(__func__);
13925 ret = __wlan_hdd_cfg80211_resume_wlan(wiphy);
13926 vos_ssr_unprotect(__func__);
13927
13928 return ret;
13929}
13930
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013931/*
Mahesh A Saptasagarbcc5b662014-06-02 21:46:23 +053013932 * FUNCTION: __wlan_hdd_cfg80211_suspend_wlan
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013933 * this is called when cfg80211 driver suspends
13934 */
Mahesh A Saptasagarbcc5b662014-06-02 21:46:23 +053013935int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053013936 struct cfg80211_wowlan *wow)
13937{
13938 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13939
13940 ENTER();
13941 if (NULL == pHddCtx)
13942 {
13943 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13944 "%s: HddCtx validation failed", __func__);
13945 return 0;
13946 }
13947
13948 pHddCtx->isWiphySuspended = TRUE;
13949
13950 EXIT();
13951
13952 return 0;
13953}
13954
Mahesh A Saptasagarbcc5b662014-06-02 21:46:23 +053013955int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
13956 struct cfg80211_wowlan *wow)
13957{
13958 int ret;
13959
13960 vos_ssr_protect(__func__);
13961 ret = __wlan_hdd_cfg80211_suspend_wlan(wiphy, wow);
13962 vos_ssr_unprotect(__func__);
13963
13964 return ret;
13965}
Jeff Johnson295189b2012-06-20 16:38:30 -070013966/* cfg80211_ops */
Gopichand Nakkala747461f2013-04-24 19:24:45 +053013967static struct cfg80211_ops wlan_hdd_cfg80211_ops =
Jeff Johnson295189b2012-06-20 16:38:30 -070013968{
13969 .add_virtual_intf = wlan_hdd_add_virtual_intf,
13970 .del_virtual_intf = wlan_hdd_del_virtual_intf,
13971 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
13972 .change_station = wlan_hdd_change_station,
13973#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
13974 .add_beacon = wlan_hdd_cfg80211_add_beacon,
13975 .del_beacon = wlan_hdd_cfg80211_del_beacon,
13976 .set_beacon = wlan_hdd_cfg80211_set_beacon,
Jeff Johnson04dd8a82012-06-29 20:41:40 -070013977#else
13978 .start_ap = wlan_hdd_cfg80211_start_ap,
13979 .change_beacon = wlan_hdd_cfg80211_change_beacon,
13980 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Jeff Johnson295189b2012-06-20 16:38:30 -070013981#endif
13982 .change_bss = wlan_hdd_cfg80211_change_bss,
13983 .add_key = wlan_hdd_cfg80211_add_key,
13984 .get_key = wlan_hdd_cfg80211_get_key,
13985 .del_key = wlan_hdd_cfg80211_del_key,
13986 .set_default_key = wlan_hdd_cfg80211_set_default_key,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -080013987#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
Jeff Johnson295189b2012-06-20 16:38:30 -070013988 .set_channel = wlan_hdd_cfg80211_set_channel,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -080013989#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013990 .scan = wlan_hdd_cfg80211_scan,
13991 .connect = wlan_hdd_cfg80211_connect,
13992 .disconnect = wlan_hdd_cfg80211_disconnect,
13993 .join_ibss = wlan_hdd_cfg80211_join_ibss,
13994 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
13995 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
13996 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
13997 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
Jeff Johnson295189b2012-06-20 16:38:30 -070013998 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
13999 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
DARAM SUDHA39eede62014-02-12 11:16:40 +053014000 .mgmt_tx = wlan_hdd_mgmt_tx,
Jeff Johnson295189b2012-06-20 16:38:30 -070014001#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
14002 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14003 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14004 .set_txq_params = wlan_hdd_set_txq_params,
14005#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014006 .get_station = wlan_hdd_cfg80211_get_station,
14007 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14008 .del_station = wlan_hdd_cfg80211_del_station,
Jeff Johnson04dd8a82012-06-29 20:41:40 -070014009 .add_station = wlan_hdd_cfg80211_add_station,
14010#ifdef FEATURE_WLAN_LFR
14011 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14012 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14013 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
14014#endif
Madan Mohan Koyyalamudiea773882012-11-02 13:37:21 -070014015#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
14016 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14017#endif
Mohit Khanna698ba2a2012-12-04 15:08:18 -080014018#ifdef FEATURE_WLAN_TDLS
14019 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14020 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14021#endif
Gopichand Nakkala870cbae2013-03-15 21:16:09 +053014022#ifdef WLAN_FEATURE_GTK_OFFLOAD
14023 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14024#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Gopichand Nakkala8e93fde2013-05-10 17:40:12 +053014025#ifdef FEATURE_WLAN_SCAN_PNO
14026 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14027 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14028#endif /*FEATURE_WLAN_SCAN_PNO */
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053014029 .resume = wlan_hdd_cfg80211_resume_wlan,
14030 .suspend = wlan_hdd_cfg80211_suspend_wlan,
Gopichand Nakkalac005b7c2013-05-14 16:04:14 +053014031 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
Leo Chang9056f462013-08-01 19:21:11 -070014032#ifdef WLAN_NL80211_TESTMODE
14033 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14034#endif
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053014035 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Jeff Johnson295189b2012-06-20 16:38:30 -070014036};
14037