blob: 9176680ed33f08690b7feda61b42531f0f37456d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#ifdef CONFIG_CNSS
46#include <net/cnss.h>
47#endif
48#include <wlan_hdd_wowl.h>
49#include <ani_global.h>
50#include "sir_params.h"
51#include "dot11f.h"
52#include "wlan_hdd_assoc.h"
53#include "wlan_hdd_wext.h"
54#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070055#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "wlan_hdd_softap_tx_rx.h"
60#include "wlan_hdd_main.h"
61#include "wlan_hdd_power.h"
62#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "cds_utils.h"
66#include "cds_sched.h"
67#include "wlan_hdd_scan.h"
68#include <qc_sap_ioctl.h>
69#include "wlan_hdd_tdls.h"
70#include "wlan_hdd_wmm.h"
71#include "wma_types.h"
72#include "wlan_hdd_misc.h"
73#include "wlan_hdd_nan.h"
74#include <wlan_hdd_ipa.h>
75#include "wlan_logging_sock_svc.h"
76
77#ifdef FEATURE_WLAN_EXTSCAN
78#include "wlan_hdd_ext_scan.h"
79#endif
80
81#ifdef WLAN_FEATURE_LINK_LAYER_STATS
82#include "wlan_hdd_stats.h"
83#endif
84#include "cds_concurrency.h"
85#include "qwlan_version.h"
86#include "wlan_hdd_memdump.h"
87
88#include "wlan_hdd_ocb.h"
89
Ravi Joshideb5a8d2015-11-09 19:11:43 -080090#include "wlan_hdd_subnet_detect.h"
91
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#define g_mode_rates_size (12)
93#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
95 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
96
97/*
98 * Android CTS verifier needs atleast this much wait time (in msec)
99 */
100#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
101
102/*
103 * Refer @tCfgProtection structure for definition of the bit map.
104 * below value is obtained by setting the following bit-fields.
105 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
106 */
107#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
108
109#define HDD2GHZCHAN(freq, chan, flag) { \
110 .band = IEEE80211_BAND_2GHZ, \
111 .center_freq = (freq), \
112 .hw_value = (chan), \
113 .flags = (flag), \
114 .max_antenna_gain = 0, \
115 .max_power = 30, \
116}
117
118#define HDD5GHZCHAN(freq, chan, flag) { \
119 .band = IEEE80211_BAND_5GHZ, \
120 .center_freq = (freq), \
121 .hw_value = (chan), \
122 .flags = (flag), \
123 .max_antenna_gain = 0, \
124 .max_power = 30, \
125}
126
127#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
128 { \
129 .bitrate = rate, \
130 .hw_value = rate_id, \
131 .flags = flag, \
132 }
133
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
135#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136
137#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800138
Peng Xu4d67c8f2015-10-16 16:02:26 -0700139#define MAX_TXPOWER_SCALE 4
140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800141static const u32 hdd_cipher_suites[] = {
142 WLAN_CIPHER_SUITE_WEP40,
143 WLAN_CIPHER_SUITE_WEP104,
144 WLAN_CIPHER_SUITE_TKIP,
145#ifdef FEATURE_WLAN_ESE
146#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
147#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
148 WLAN_CIPHER_SUITE_BTK,
149 WLAN_CIPHER_SUITE_KRK,
150 WLAN_CIPHER_SUITE_CCMP,
151#else
152 WLAN_CIPHER_SUITE_CCMP,
153#endif
154#ifdef FEATURE_WLAN_WAPI
155 WLAN_CIPHER_SUITE_SMS4,
156#endif
157#ifdef WLAN_FEATURE_11W
158 WLAN_CIPHER_SUITE_AES_CMAC,
159#endif
160};
161
162static struct ieee80211_channel hdd_channels_2_4_ghz[] = {
163 HDD2GHZCHAN(2412, 1, 0),
164 HDD2GHZCHAN(2417, 2, 0),
165 HDD2GHZCHAN(2422, 3, 0),
166 HDD2GHZCHAN(2427, 4, 0),
167 HDD2GHZCHAN(2432, 5, 0),
168 HDD2GHZCHAN(2437, 6, 0),
169 HDD2GHZCHAN(2442, 7, 0),
170 HDD2GHZCHAN(2447, 8, 0),
171 HDD2GHZCHAN(2452, 9, 0),
172 HDD2GHZCHAN(2457, 10, 0),
173 HDD2GHZCHAN(2462, 11, 0),
174 HDD2GHZCHAN(2467, 12, 0),
175 HDD2GHZCHAN(2472, 13, 0),
176 HDD2GHZCHAN(2484, 14, 0),
177};
178
179static struct ieee80211_channel hdd_social_channels_2_4_ghz[] = {
180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2437, 6, 0),
182 HDD2GHZCHAN(2462, 11, 0),
183};
184
185static struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186 HDD5GHZCHAN(5180, 36, 0),
187 HDD5GHZCHAN(5200, 40, 0),
188 HDD5GHZCHAN(5220, 44, 0),
189 HDD5GHZCHAN(5240, 48, 0),
190 HDD5GHZCHAN(5260, 52, 0),
191 HDD5GHZCHAN(5280, 56, 0),
192 HDD5GHZCHAN(5300, 60, 0),
193 HDD5GHZCHAN(5320, 64, 0),
194 HDD5GHZCHAN(5500, 100, 0),
195 HDD5GHZCHAN(5520, 104, 0),
196 HDD5GHZCHAN(5540, 108, 0),
197 HDD5GHZCHAN(5560, 112, 0),
198 HDD5GHZCHAN(5580, 116, 0),
199 HDD5GHZCHAN(5600, 120, 0),
200 HDD5GHZCHAN(5620, 124, 0),
201 HDD5GHZCHAN(5640, 128, 0),
202 HDD5GHZCHAN(5660, 132, 0),
203 HDD5GHZCHAN(5680, 136, 0),
204 HDD5GHZCHAN(5700, 140, 0),
205 HDD5GHZCHAN(5720, 144, 0),
206 HDD5GHZCHAN(5745, 149, 0),
207 HDD5GHZCHAN(5765, 153, 0),
208 HDD5GHZCHAN(5785, 157, 0),
209 HDD5GHZCHAN(5805, 161, 0),
210 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211 HDD5GHZCHAN(5852, 170, 0),
212 HDD5GHZCHAN(5855, 171, 0),
213 HDD5GHZCHAN(5860, 172, 0),
214 HDD5GHZCHAN(5865, 173, 0),
215 HDD5GHZCHAN(5870, 174, 0),
216 HDD5GHZCHAN(5875, 175, 0),
217 HDD5GHZCHAN(5880, 176, 0),
218 HDD5GHZCHAN(5885, 177, 0),
219 HDD5GHZCHAN(5890, 178, 0),
220 HDD5GHZCHAN(5895, 179, 0),
221 HDD5GHZCHAN(5900, 180, 0),
222 HDD5GHZCHAN(5905, 181, 0),
223 HDD5GHZCHAN(5910, 182, 0),
224 HDD5GHZCHAN(5915, 183, 0),
225 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226};
227
228static struct ieee80211_rate g_mode_rates[] = {
229 HDD_G_MODE_RATETAB(10, 0x1, 0),
230 HDD_G_MODE_RATETAB(20, 0x2, 0),
231 HDD_G_MODE_RATETAB(55, 0x4, 0),
232 HDD_G_MODE_RATETAB(110, 0x8, 0),
233 HDD_G_MODE_RATETAB(60, 0x10, 0),
234 HDD_G_MODE_RATETAB(90, 0x20, 0),
235 HDD_G_MODE_RATETAB(120, 0x40, 0),
236 HDD_G_MODE_RATETAB(180, 0x80, 0),
237 HDD_G_MODE_RATETAB(240, 0x100, 0),
238 HDD_G_MODE_RATETAB(360, 0x200, 0),
239 HDD_G_MODE_RATETAB(480, 0x400, 0),
240 HDD_G_MODE_RATETAB(540, 0x800, 0),
241};
242
243static struct ieee80211_rate a_mode_rates[] = {
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
255 .channels = hdd_channels_2_4_ghz,
256 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
257 .band = IEEE80211_BAND_2GHZ,
258 .bitrates = g_mode_rates,
259 .n_bitrates = g_mode_rates_size,
260 .ht_cap.ht_supported = 1,
261 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
262 | IEEE80211_HT_CAP_GRN_FLD
263 | IEEE80211_HT_CAP_DSSSCCK40
264 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
265 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
266 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
267 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
268 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
269 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
270 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
271};
272
273static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_ghz = {
274 .channels = hdd_social_channels_2_4_ghz,
275 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_ghz),
276 .band = IEEE80211_BAND_2GHZ,
277 .bitrates = g_mode_rates,
278 .n_bitrates = g_mode_rates_size,
279 .ht_cap.ht_supported = 1,
280 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
281 | IEEE80211_HT_CAP_GRN_FLD
282 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
283 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
284 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
285 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
286 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
287 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
288};
289
290static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
291 .channels = hdd_channels_5_ghz,
292 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
293 .band = IEEE80211_BAND_5GHZ,
294 .bitrates = a_mode_rates,
295 .n_bitrates = a_mode_rates_size,
296 .ht_cap.ht_supported = 1,
297 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
298 | IEEE80211_HT_CAP_GRN_FLD
299 | IEEE80211_HT_CAP_DSSSCCK40
300 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
301 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
302 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
303 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
304 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
305 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
306 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
307 .vht_cap.vht_supported = 1,
308};
309
310/* This structure contain information what kind of frame are expected in
311 TX/RX direction for each kind of interface */
312static const struct ieee80211_txrx_stypes
313 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
314 [NL80211_IFTYPE_STATION] = {
315 .tx = 0xffff,
316 .rx = BIT(SIR_MAC_MGMT_ACTION) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ),
318 },
319 [NL80211_IFTYPE_AP] = {
320 .tx = 0xffff,
321 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
322 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
323 BIT(SIR_MAC_MGMT_PROBE_REQ) |
324 BIT(SIR_MAC_MGMT_DISASSOC) |
325 BIT(SIR_MAC_MGMT_AUTH) |
326 BIT(SIR_MAC_MGMT_DEAUTH) |
327 BIT(SIR_MAC_MGMT_ACTION),
328 },
329 [NL80211_IFTYPE_ADHOC] = {
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_PROBE_REQ) |
334 BIT(SIR_MAC_MGMT_DISASSOC) |
335 BIT(SIR_MAC_MGMT_AUTH) |
336 BIT(SIR_MAC_MGMT_DEAUTH) |
337 BIT(SIR_MAC_MGMT_ACTION),
338 },
339 [NL80211_IFTYPE_P2P_CLIENT] = {
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ACTION) |
342 BIT(SIR_MAC_MGMT_PROBE_REQ),
343 },
344 [NL80211_IFTYPE_P2P_GO] = {
345 /* This is also same as for SoftAP */
346 .tx = 0xffff,
347 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
348 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ) |
350 BIT(SIR_MAC_MGMT_DISASSOC) |
351 BIT(SIR_MAC_MGMT_AUTH) |
352 BIT(SIR_MAC_MGMT_DEAUTH) |
353 BIT(SIR_MAC_MGMT_ACTION),
354 },
355};
356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357/* Interface limits and combinations registered by the driver */
358
359/* STA ( + STA ) combination */
360static const struct ieee80211_iface_limit
361 wlan_hdd_sta_iface_limit[] = {
362 {
363 .max = 3, /* p2p0 is a STA as well */
364 .types = BIT(NL80211_IFTYPE_STATION),
365 },
366};
367
Krunal Soni7bc4f912015-11-15 23:41:56 -0800368#ifndef QCA_WIFI_3_0_EMU
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369/* ADHOC (IBSS) limit */
370static const struct ieee80211_iface_limit
371 wlan_hdd_adhoc_iface_limit[] = {
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_STATION),
375 },
376 {
377 .max = 1,
378 .types = BIT(NL80211_IFTYPE_ADHOC),
379 },
380};
Krunal Soni7bc4f912015-11-15 23:41:56 -0800381#else
382/* ADHOC (IBSS) limit */
383static const struct ieee80211_iface_limit
384 wlan_hdd_adhoc_iface_limit[] = {
385 {
386 .max = 1,
387 .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
388 },
389 {
390 .max = 1,
391 .types = BIT(NL80211_IFTYPE_ADHOC),
392 },
393};
394#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800395
396/* AP ( + AP ) combination */
397static const struct ieee80211_iface_limit
398 wlan_hdd_ap_iface_limit[] = {
399 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530400 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 .types = BIT(NL80211_IFTYPE_AP),
402 },
403};
404
405/* P2P limit */
406static const struct ieee80211_iface_limit
407 wlan_hdd_p2p_iface_limit[] = {
408 {
409 .max = 1,
410 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
411 },
412 {
413 .max = 1,
414 .types = BIT(NL80211_IFTYPE_P2P_GO),
415 },
416};
417
418static const struct ieee80211_iface_limit
419 wlan_hdd_sta_ap_iface_limit[] = {
420 {
421 /* We need 1 extra STA interface for OBSS scan when SAP starts
422 * with HT40 in STA+SAP concurrency mode
423 */
424 .max = (1 + SAP_MAX_OBSS_STA_CNT),
425 .types = BIT(NL80211_IFTYPE_STATION),
426 },
427 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530428 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429 .types = BIT(NL80211_IFTYPE_AP),
430 },
431};
432
433/* STA + P2P combination */
434static const struct ieee80211_iface_limit
435 wlan_hdd_sta_p2p_iface_limit[] = {
436 {
437 /* One reserved for dedicated P2PDEV usage */
438 .max = 2,
439 .types = BIT(NL80211_IFTYPE_STATION)
440 },
441 {
442 /* Support for two identical (GO + GO or CLI + CLI)
443 * or dissimilar (GO + CLI) P2P interfaces
444 */
445 .max = 2,
446 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
447 },
448};
449
450/* STA + AP + P2PGO combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
453 /* Support for AP+P2PGO interfaces */
454 {
455 .max = 2,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO)
461 },
462 {
463 .max = 1,
464 .types = BIT(NL80211_IFTYPE_AP)
465 }
466};
467
468/* SAP + P2P combination */
469static const struct ieee80211_iface_limit
470wlan_hdd_sap_p2p_iface_limit[] = {
471 {
472 /* 1 dedicated for p2p0 which is a STA type */
473 .max = 1,
474 .types = BIT(NL80211_IFTYPE_STATION)
475 },
476 {
477 /* The p2p interface in SAP+P2P can be GO/CLI.
478 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
479 */
480 .max = 1,
481 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
482 },
483 {
484 /* SAP+GO to support only one SAP interface */
485 .max = 1,
486 .types = BIT(NL80211_IFTYPE_AP)
487 }
488};
489
490/* P2P + P2P combination */
491static const struct ieee80211_iface_limit
492wlan_hdd_p2p_p2p_iface_limit[] = {
493 {
494 /* 1 dedicated for p2p0 which is a STA type */
495 .max = 1,
496 .types = BIT(NL80211_IFTYPE_STATION)
497 },
498 {
499 /* The p2p interface in P2P+P2P can be GO/CLI.
500 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
501 */
502 .max = 2,
503 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
504 },
505};
506
507static struct ieee80211_iface_combination
508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
584};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586static struct cfg80211_ops wlan_hdd_cfg80211_ops;
587
588
589#ifdef WLAN_NL80211_TESTMODE
590enum wlan_hdd_tm_attr {
591 WLAN_HDD_TM_ATTR_INVALID = 0,
592 WLAN_HDD_TM_ATTR_CMD = 1,
593 WLAN_HDD_TM_ATTR_DATA = 2,
594 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
595 WLAN_HDD_TM_ATTR_TYPE = 4,
596 /* keep last */
597 WLAN_HDD_TM_ATTR_AFTER_LAST,
598 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
599};
600
601enum wlan_hdd_tm_cmd {
602 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
603 WLAN_HDD_TM_CMD_WLAN_HB = 1,
604};
605
606#define WLAN_HDD_TM_DATA_MAX_LEN 5000
607
608static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
609 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
610 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
611 .len = WLAN_HDD_TM_DATA_MAX_LEN},
612};
613#endif /* WLAN_NL80211_TESTMODE */
614
615#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
616static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
617 .flags = WIPHY_WOWLAN_MAGIC_PKT,
618 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
619 .pattern_min_len = 1,
620 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
621};
622#endif
623
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530625 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
626 * @flags: Pointer to the flags to Add channel switch flag.
627 *
628 * This Function adds Channel Switch support flag, if channel switch is
629 * supported by kernel.
630 * Return: void.
631 */
632#ifdef CHANNEL_SWITCH_SUPPORTED
633static inline void hdd_add_channel_switch_support(uint32_t *flags)
634{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800635 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 return;
637}
638#else
639static inline void hdd_add_channel_switch_support(uint32_t *flags)
640{
641 return;
642}
643#endif
644
Manikandan Mohan22b83722015-12-15 15:03:23 -0800645#ifdef FEATURE_WLAN_TDLS
646
647/* TDLS capabilities params */
648#define PARAM_MAX_TDLS_SESSION \
649 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
650#define PARAM_TDLS_FEATURE_SUPPORT \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
652
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530653/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
655 * @wiphy: WIPHY structure pointer
656 * @wdev: Wireless device structure pointer
657 * @data: Pointer to the data received
658 * @data_len: Length of the data received
659 *
660 * This function provides TDLS capabilities
661 *
662 * Return: 0 on success and errno on failure
663 */
664static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
665 struct wireless_dev *wdev,
666 const void *data,
667 int data_len)
668{
669 int status;
670 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
671 struct sk_buff *skb;
672 uint32_t set = 0;
673
Jeff Johnson1f61b612016-02-12 16:28:33 -0800674 ENTER_DEV(wdev->netdev);
675
Anurag Chouhan6d760662016-02-20 16:05:43 +0530676 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677 hdd_err("Command not allowed in FTM mode");
678 return -EPERM;
679 }
680
681 status = wlan_hdd_validate_context(hdd_ctx);
682 if (status)
683 return status;
684
685 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
686 NLMSG_HDRLEN);
687 if (!skb) {
688 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
689 goto fail;
690 }
691
692 if (false == hdd_ctx->config->fEnableTDLSSupport) {
693 hddLog(LOGE,
694 FL("TDLS feature not Enabled or Not supported in FW"));
695 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
696 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
697 hddLog(LOGE, FL("nla put fail"));
698 goto fail;
699 }
700 } else {
701 set = set | WIFI_TDLS_SUPPORT;
702 set = set | (hdd_ctx->config->fTDLSExternalControl ?
703 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
704 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
705 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
706 hddLog(LOG1, FL("TDLS Feature supported value %x"), set);
707 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
708 hdd_ctx->max_num_tdls_sta) ||
709 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
710 set)) {
711 hddLog(LOGE, FL("nla put fail"));
712 goto fail;
713 }
714 }
715 return cfg80211_vendor_cmd_reply(skb);
716fail:
717 if (skb)
718 kfree_skb(skb);
719 return -EINVAL;
720}
721
722/**
723 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
724 * @wiphy: WIPHY structure pointer
725 * @wdev: Wireless device structure pointer
726 * @data: Pointer to the data received
727 * @data_len: Length of the data received
728 *
729 * This function provides TDLS capabilities
730 *
731 * Return: 0 on success and errno on failure
732 */
733static int
734wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
735 struct wireless_dev *wdev,
736 const void *data,
737 int data_len)
738{
739 int ret;
740
741 cds_ssr_protect(__func__);
742 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
743 data, data_len);
744 cds_ssr_unprotect(__func__);
745
746 return ret;
747}
748#endif
749
750#ifdef QCA_HT_2040_COEX
751static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
752#endif
753
754#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
755/*
756 * FUNCTION: wlan_hdd_send_avoid_freq_event
757 * This is called when wlan driver needs to send vendor specific
758 * avoid frequency range event to userspace
759 */
760int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
761 tHddAvoidFreqList *pAvoidFreqList)
762{
763 struct sk_buff *vendor_event;
764
765 ENTER();
766
767 if (!pHddCtx) {
768 hddLog(LOGE, FL("HDD context is null"));
769 return -EINVAL;
770 }
771
772 if (!pAvoidFreqList) {
773 hddLog(LOGE, FL("pAvoidFreqList is null"));
774 return -EINVAL;
775 }
776
777 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
778 NULL,
779 sizeof(tHddAvoidFreqList),
780 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
781 GFP_KERNEL);
782 if (!vendor_event) {
783 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
784 return -EINVAL;
785 }
786
787 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
788 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
789
790 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
791
792 EXIT();
793 return 0;
794}
795#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
796
797/* vendor specific events */
798static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
799#ifdef FEATURE_WLAN_CH_AVOID
800 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
801 .vendor_id =
802 QCA_NL80211_VENDOR_ID,
803 .subcmd =
804 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
805 },
806#endif /* FEATURE_WLAN_CH_AVOID */
807
808#ifdef WLAN_FEATURE_NAN
809 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
810 .vendor_id =
811 QCA_NL80211_VENDOR_ID,
812 .subcmd =
813 QCA_NL80211_VENDOR_SUBCMD_NAN
814 },
815#endif
816
817#ifdef WLAN_FEATURE_STATS_EXT
818 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
819 .vendor_id =
820 QCA_NL80211_VENDOR_ID,
821 .subcmd =
822 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
823 },
824#endif /* WLAN_FEATURE_STATS_EXT */
825#ifdef FEATURE_WLAN_EXTSCAN
826 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
827 .vendor_id =
828 QCA_NL80211_VENDOR_ID,
829 .subcmd =
830 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
831 },
832 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
833 .vendor_id =
834 QCA_NL80211_VENDOR_ID,
835 .subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
839 .
840 vendor_id
841 =
842 QCA_NL80211_VENDOR_ID,
843 .subcmd =
844 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
845 },
846 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
847 .
848 vendor_id
849 =
850 QCA_NL80211_VENDOR_ID,
851 .
852 subcmd =
853 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
854 },
855 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
856 .
857 vendor_id
858 =
859 QCA_NL80211_VENDOR_ID,
860 .
861 subcmd
862 =
863 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
864 },
865 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
866 .
867 vendor_id
868 =
869 QCA_NL80211_VENDOR_ID,
870 .subcmd =
871 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
872 },
873 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
874 .vendor_id =
875 QCA_NL80211_VENDOR_ID,
876 .subcmd =
877 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
878 },
879 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
880 .
881 vendor_id
882 =
883 QCA_NL80211_VENDOR_ID,
884 .subcmd =
885 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
886 },
887 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
888 .
889 vendor_id
890 =
891 QCA_NL80211_VENDOR_ID,
892 .subcmd =
893 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
894 },
895 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
896 .
897 vendor_id
898 =
899 QCA_NL80211_VENDOR_ID,
900 .
901 subcmd
902 =
903 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
904 },
905 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
906 .
907 vendor_id
908 =
909 QCA_NL80211_VENDOR_ID,
910 .
911 subcmd =
912 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
913 },
914 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
915 .
916 vendor_id
917 =
918 QCA_NL80211_VENDOR_ID,
919 .
920 subcmd
921 =
922 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
923 },
924 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
925 .
926 vendor_id
927 =
928 QCA_NL80211_VENDOR_ID,
929 .
930 subcmd
931 =
932 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
933 },
934 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
935 .vendor_id = QCA_NL80211_VENDOR_ID,
936 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
937 },
938 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
939 .vendor_id = QCA_NL80211_VENDOR_ID,
940 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
941 },
942#endif /* FEATURE_WLAN_EXTSCAN */
943
944#ifdef WLAN_FEATURE_LINK_LAYER_STATS
945 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
946 .vendor_id =
947 QCA_NL80211_VENDOR_ID,
948 .subcmd =
949 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
950 },
951 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
952 .vendor_id =
953 QCA_NL80211_VENDOR_ID,
954 .subcmd =
955 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
956 },
957 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
958 .vendor_id =
959 QCA_NL80211_VENDOR_ID,
960 .subcmd =
961 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
962 },
963 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
964 .vendor_id =
965 QCA_NL80211_VENDOR_ID,
966 .subcmd =
967 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
968 },
969 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
970 .vendor_id =
971 QCA_NL80211_VENDOR_ID,
972 .subcmd =
973 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
974 },
975 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
976 .vendor_id =
977 QCA_NL80211_VENDOR_ID,
978 .subcmd =
979 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
980 },
981#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
982 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
987 },
988 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
989 .vendor_id = QCA_NL80211_VENDOR_ID,
990 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
991 },
992#ifdef WLAN_FEATURE_ROAM_OFFLOAD
993 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
994 .vendor_id =
995 QCA_NL80211_VENDOR_ID,
996 .subcmd =
997 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
998 },
999#endif
1000 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1005 },
1006 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1007 .vendor_id =
1008 QCA_NL80211_VENDOR_ID,
1009 .subcmd =
1010 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1011 },
1012 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1019 .vendor_id =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1025 .vendor_id =
1026 QCA_NL80211_VENDOR_ID,
1027 .subcmd =
1028 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1029 },
1030#ifdef FEATURE_WLAN_EXTSCAN
1031 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1032 .vendor_id = QCA_NL80211_VENDOR_ID,
1033 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1034 },
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1038 },
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1042 },
1043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1046 },
1047 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1048 .vendor_id = QCA_NL80211_VENDOR_ID,
1049 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1050 },
1051#endif /* FEATURE_WLAN_EXTSCAN */
1052 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1053 .vendor_id = QCA_NL80211_VENDOR_ID,
1054 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1055 },
1056#ifdef WLAN_FEATURE_MEMDUMP
1057 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1058 .vendor_id = QCA_NL80211_VENDOR_ID,
1059 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1060 },
1061#endif /* WLAN_FEATURE_MEMDUMP */
1062 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1063 .vendor_id = QCA_NL80211_VENDOR_ID,
1064 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1065 },
1066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1069 },
1070 /* OCB events */
1071 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1072 .vendor_id = QCA_NL80211_VENDOR_ID,
1073 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1074 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001075#ifdef FEATURE_LFR_SUBNET_DETECTION
1076 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1077 .vendor_id = QCA_NL80211_VENDOR_ID,
1078 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1079 },
1080#endif /*FEATURE_LFR_SUBNET_DETECTION */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001081};
1082
1083/**
1084 * __is_driver_dfs_capable() - get driver DFS capability
1085 * @wiphy: pointer to wireless wiphy structure.
1086 * @wdev: pointer to wireless_dev structure.
1087 * @data: Pointer to the data to be passed via vendor interface
1088 * @data_len:Length of the data to be passed
1089 *
1090 * This function is called by userspace to indicate whether or not
1091 * the driver supports DFS offload.
1092 *
1093 * Return: 0 on success, negative errno on failure
1094 */
1095static int __is_driver_dfs_capable(struct wiphy *wiphy,
1096 struct wireless_dev *wdev,
1097 const void *data,
1098 int data_len)
1099{
1100 u32 dfs_capability = 0;
1101 struct sk_buff *temp_skbuff;
1102 int ret_val;
1103 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1104
Jeff Johnson1f61b612016-02-12 16:28:33 -08001105 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106
1107 ret_val = wlan_hdd_validate_context(hdd_ctx);
1108 if (ret_val)
1109 return ret_val;
1110
Anurag Chouhan6d760662016-02-20 16:05:43 +05301111 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001112 hdd_err("Command not allowed in FTM mode");
1113 return -EPERM;
1114 }
1115
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117
1118 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1119 NLMSG_HDRLEN);
1120
1121 if (temp_skbuff != NULL) {
1122 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1123 dfs_capability);
1124 if (ret_val) {
1125 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail"));
1126 kfree_skb(temp_skbuff);
1127
1128 return ret_val;
1129 }
1130
1131 return cfg80211_vendor_cmd_reply(temp_skbuff);
1132 }
1133
1134 hddLog(LOGE, FL("dfs capability: buffer alloc fail"));
1135 return -ENOMEM;
1136}
1137
1138/**
1139 * is_driver_dfs_capable() - get driver DFS capability
1140 * @wiphy: pointer to wireless wiphy structure.
1141 * @wdev: pointer to wireless_dev structure.
1142 * @data: Pointer to the data to be passed via vendor interface
1143 * @data_len:Length of the data to be passed
1144 *
1145 * This function is called by userspace to indicate whether or not
1146 * the driver supports DFS offload. This is an SSR-protected
1147 * wrapper function.
1148 *
1149 * Return: 0 on success, negative errno on failure
1150 */
1151static int is_driver_dfs_capable(struct wiphy *wiphy,
1152 struct wireless_dev *wdev,
1153 const void *data,
1154 int data_len)
1155{
1156 int ret;
1157
1158 cds_ssr_protect(__func__);
1159 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1160 cds_ssr_unprotect(__func__);
1161
1162 return ret;
1163}
1164
1165/**
1166 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1167 *
1168 * @adapter: SAP adapter pointer
1169 *
1170 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1171 * radio. So in case of DFS MCC scenario override current SAP given config
1172 * to follow concurrent SAP DFS config
1173 *
1174 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1175 */
1176
1177#ifdef WLAN_FEATURE_MBSSID
1178int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1179{
1180 hdd_adapter_t *con_sap_adapter;
1181 tsap_Config_t *sap_config, *con_sap_config;
1182 int con_ch;
1183
1184 /*
1185 * Check if AP+AP case, once primary AP chooses a DFS
1186 * channel secondary AP should always follow primary APs channel
1187 */
1188 if (!cds_concurrent_beaconing_sessions_running())
1189 return 0;
1190
1191 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1192 if (!con_sap_adapter)
1193 return 0;
1194
1195 sap_config = &adapter->sessionCtx.ap.sapConfig;
1196 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1197 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1198
1199 if (!CDS_IS_DFS_CH(con_ch))
1200 return 0;
1201
1202 hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"),
1203 sap_config->channel, con_ch);
1204 hddLog(LOG1, FL("Overriding guest AP's channel"));
1205 sap_config->channel = con_ch;
1206
1207 if (con_sap_config->acs_cfg.acs_mode == true) {
1208 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1209 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
1210 hddLog(LOGE, FL("Primary AP channel config error"));
1211 hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"),
1212 con_ch, con_sap_config->acs_cfg.pri_ch,
1213 con_sap_config->acs_cfg.ht_sec_ch);
1214 return -EINVAL;
1215 }
1216 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1217 * MCC restriction. So free ch list allocated in do_acs
1218 * func for Sec AP and realloc for Pri AP ch list size
1219 */
1220 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301221 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301223 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001224 &con_sap_config->acs_cfg,
1225 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301226 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 sizeof(uint8_t) *
1228 con_sap_config->acs_cfg.ch_list_count);
1229 if (!sap_config->acs_cfg.ch_list) {
1230 hddLog(LOGE, FL("ACS config alloc fail"));
1231 return -ENOMEM;
1232 }
1233
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301234 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 con_sap_config->acs_cfg.ch_list,
1236 con_sap_config->acs_cfg.ch_list_count);
1237
1238 } else {
1239 sap_config->acs_cfg.pri_ch = con_ch;
1240 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1241 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1242 }
1243
1244 return con_ch;
1245}
1246#else
1247int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1248{
1249 return 0;
1250}
1251#endif
1252
1253/**
1254 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1255 * @sap_cfg: pointer to SAP config struct
1256 *
1257 * This function sets the default ACS start and end channel for the given band
1258 * and also parses the given ACS channel list.
1259 *
1260 * Return: None
1261 */
1262
1263static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1264 bool vht_enabled)
1265{
1266 int i;
1267 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1268 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001269 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1);
1270 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1272 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001273 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1);
1274 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001275 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1276 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001277 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_36);
1278 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1280 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhal7a1726a2015-10-14 16:28:11 -07001281 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(RF_CHAN_1);
1282 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(RF_CHAN_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 }
1284
1285 if (ht_enabled)
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1287
1288 if (vht_enabled)
1289 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1290
1291
1292 /* Parse ACS Chan list from hostapd */
1293 if (!sap_cfg->acs_cfg.ch_list)
1294 return;
1295
1296 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1297 sap_cfg->acs_cfg.end_ch =
1298 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1299 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
1300 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i])
1301 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1302 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1303 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1304 }
1305}
1306
1307
1308static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1309
1310/**
1311 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1312 * @adapter: pointer to SAP adapter struct
1313 *
1314 * This function starts the ACS procedure if there are no
1315 * constraints like MBSSID DFS restrictions.
1316 *
1317 * Return: Status of ACS Start procedure
1318 */
1319
1320static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1321{
1322
1323 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1324 tsap_Config_t *sap_config;
1325 tpWLAN_SAPEventCB acs_event_callback;
1326 int status;
1327
1328 sap_config = &adapter->sessionCtx.ap.sapConfig;
1329 sap_config->channel = AUTO_CHANNEL_SELECT;
1330
1331 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1332 if (status < 0) {
1333 return status;
1334 } else {
1335 if (status > 0) {
1336 /*notify hostapd about channel override */
1337 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1338 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1339 return 0;
1340 }
1341 }
1342 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1343 if (status) {
1344 hddLog(LOGE, FL("ACS config failed"));
1345 return -EINVAL;
1346 }
1347
1348 acs_event_callback = hdd_hostapd_sap_event_cb;
1349
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301350 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301351 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex);
1353 status = wlansap_acs_chselect(
1354#ifdef WLAN_FEATURE_MBSSID
1355 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1356#else
1357 hdd_ctx->pcds_context,
1358#endif
1359 acs_event_callback, sap_config, adapter->dev);
1360
1361
1362 if (status) {
1363 hddLog(LOGE, FL("ACS channel select failed"));
1364 return -EINVAL;
1365 }
1366 sap_config->acs_cfg.acs_mode = true;
1367 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1368
1369 return 0;
1370}
1371
1372/**
1373 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1374 * @wiphy: Linux wiphy struct pointer
1375 * @wdev: Linux wireless device struct pointer
1376 * @data: ACS information from hostapd
1377 * @data_len: ACS information length
1378 *
1379 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1380 * and starts ACS procedure.
1381 *
1382 * Return: ACS procedure start status
1383 */
1384
1385static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1386 struct wireless_dev *wdev,
1387 const void *data, int data_len)
1388{
1389 struct net_device *ndev = wdev->netdev;
1390 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1391 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1392 tsap_Config_t *sap_config;
1393 struct sk_buff *temp_skbuff;
1394 int status = -EINVAL, i = 0;
1395 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1396 bool ht_enabled, ht40_enabled, vht_enabled;
1397 uint8_t ch_width;
1398
1399 /* ***Note*** Donot set SME config related to ACS operation here because
1400 * ACS operation is not synchronouse and ACS for Second AP may come when
1401 * ACS operation for first AP is going on. So only do_acs is split to
1402 * seperate start_acs routine. Also SME-PMAC struct that is used to
1403 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1404 * config shall be set only from start_acs.
1405 */
1406
1407 /* nla_policy Policy template. Policy not applied as some attributes are
1408 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1409 *
1410 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1411 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1412 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1413 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1414 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1415 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1416 */
1417
Jeff Johnson1f61b612016-02-12 16:28:33 -08001418 ENTER_DEV(ndev);
1419
Anurag Chouhan6d760662016-02-20 16:05:43 +05301420 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421 hdd_err("Command not allowed in FTM mode");
1422 return -EPERM;
1423 }
1424
1425 if (hdd_ctx->config->force_sap_acs) {
1426 hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled"));
1427 return -EPERM;
1428 }
1429
1430 status = wlan_hdd_validate_context(hdd_ctx);
1431 if (0 != status) {
1432 hddLog(LOGE, FL("HDD context is not valid"));
1433 goto out;
1434 }
1435 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301436 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001437
1438 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1439 NULL);
1440 if (status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301441 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001442 goto out;
1443 }
1444
1445 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301446 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 goto out;
1448 }
1449 sap_config->acs_cfg.hw_mode = nla_get_u8(
1450 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1451
1452 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1453 ht_enabled =
1454 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1455 else
1456 ht_enabled = 0;
1457
1458 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1459 ht40_enabled =
1460 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1461 else
1462 ht40_enabled = 0;
1463
1464 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1465 vht_enabled =
1466 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1467 else
1468 vht_enabled = 0;
1469
1470 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1471 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1472 } else {
1473 if (ht_enabled && ht40_enabled)
1474 ch_width = 40;
1475 else
1476 ch_width = 20;
1477 }
1478 if (ch_width == 80)
1479 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1480 else if (ch_width == 40)
1481 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1482 else
1483 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1484
1485 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1486 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1487 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1488 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1489 * since it contains the frequency values of the channels in
1490 * the channel list.
1491 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1492 * is present
1493 */
1494 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1495 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1496 sap_config->acs_cfg.ch_list_count = nla_len(
1497 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1498 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301499 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500 sizeof(uint8_t) *
1501 sap_config->acs_cfg.ch_list_count);
1502 if (sap_config->acs_cfg.ch_list == NULL)
1503 goto out;
1504
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301505 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 sap_config->acs_cfg.ch_list_count);
1507 }
1508 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1509 uint32_t *freq =
1510 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1511 sap_config->acs_cfg.ch_list_count = nla_len(
1512 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1513 sizeof(uint32_t);
1514 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301515 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516 sap_config->acs_cfg.ch_list_count);
1517 if (sap_config->acs_cfg.ch_list == NULL) {
1518 hddLog(LOGE, FL("ACS config alloc fail"));
1519 status = -ENOMEM;
1520 goto out;
1521 }
1522
1523 /* convert frequency to channel */
1524 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1525 sap_config->acs_cfg.ch_list[i] =
1526 ieee80211_frequency_to_channel(freq[i]);
1527 }
1528 }
1529
1530 hdd_debug("get pcl for DO_ACS vendor command");
1531
1532 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001533 status = cds_get_pcl(CDS_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534 sap_config->acs_cfg.pcl_channels,
1535 &sap_config->acs_cfg.pcl_ch_count);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301536 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 hddLog(LOGE, FL("Get PCL failed"));
1538
1539 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1540
1541 /* ACS override for android */
1542 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
1543 hddLog(LOG1, FL("ACS Config override for 11AC"));
1544 vht_enabled = 1;
1545 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1546 sap_config->acs_cfg.ch_width =
1547 hdd_ctx->config->vhtChannelWidth;
1548 /* No VHT80 in 2.4G so perform ACS accordingly */
1549 if (sap_config->acs_cfg.end_ch <= 14 &&
1550 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1551 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1552 }
1553
1554 hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"),
1555 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1556 ch_width, ht_enabled, vht_enabled,
1557 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1558
1559 if (sap_config->acs_cfg.ch_list_count) {
1560 hddLog(LOG1, FL("ACS channel list: len: %d"),
1561 sap_config->acs_cfg.ch_list_count);
1562 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1563 hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]);
1564 }
1565 sap_config->acs_cfg.acs_mode = true;
1566 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
1567 /* ***Note*** Completion variable usage is not allowed here since
1568 * ACS scan operation may take max 2.2 sec for 5G band.
1569 * 9 Active channel X 40 ms active scan time +
1570 * 16 Passive channel X 110ms passive scan time
1571 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1572 * for this long. So we split up the scanning part.
1573 */
1574 set_bit(ACS_PENDING, &adapter->event_flags);
1575 hddLog(LOG1, FL("ACS Pending for wlan%d"),
1576 adapter->dev->ifindex);
1577 status = 0;
1578 } else {
1579 status = wlan_hdd_cfg80211_start_acs(adapter);
1580 }
1581
1582out:
1583 if (0 == status) {
1584 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1585 NLMSG_HDRLEN);
1586 if (temp_skbuff != NULL)
1587 return cfg80211_vendor_cmd_reply(temp_skbuff);
1588 }
1589
1590 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1591
1592 return status;
1593}
1594
1595 /**
1596 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1597 * @wiphy: Linux wiphy struct pointer
1598 * @wdev: Linux wireless device struct pointer
1599 * @data: ACS information from hostapd
1600 * @data_len: ACS information len
1601 *
1602 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1603 * and starts ACS procedure.
1604 *
1605 * Return: ACS procedure start status
1606 */
1607
1608static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1609 struct wireless_dev *wdev,
1610 const void *data, int data_len)
1611{
1612 int ret;
1613
1614 cds_ssr_protect(__func__);
1615 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1616 cds_ssr_unprotect(__func__);
1617
1618 return ret;
1619}
1620
1621/**
1622 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1623 * @work: Linux workqueue struct pointer for ACS work
1624 *
1625 * This function starts the ACS procedure which was marked pending when an ACS
1626 * procedure was in progress for a concurrent SAP interface.
1627 *
1628 * Return: None
1629 */
1630
1631static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1632{
1633 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1634 acs_pending_work.work);
1635 wlan_hdd_cfg80211_start_acs(adapter);
1636}
1637
1638/**
1639 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1640 * @adapter: Pointer to SAP adapter struct
1641 * @pri_channel: SAP ACS procedure selected Primary channel
1642 * @sec_channel: SAP ACS procedure selected secondary channel
1643 *
1644 * This is a callback function from SAP module on ACS procedure is completed.
1645 * This function send the ACS selected channel information to hostapd
1646 *
1647 * Return: None
1648 */
1649
1650void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1651{
1652 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1653 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1654 struct sk_buff *vendor_event;
1655 int ret_val;
1656 hdd_adapter_t *con_sap_adapter;
1657 uint16_t ch_width;
1658
1659 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1660 NULL,
1661 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1662 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1663 GFP_KERNEL);
1664
1665 if (!vendor_event) {
1666 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
1667 return;
1668 }
1669
1670 ret_val = hdd_vendor_put_ifindex(vendor_event, adapter->dev->ifindex);
1671 if (ret_val) {
1672 hddLog(LOGE, FL("NL80211_ATTR_IFINDEX put fail"));
1673 kfree_skb(vendor_event);
1674 return;
1675 }
1676
1677 ret_val = nla_put_u8(vendor_event,
1678 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1679 sap_cfg->acs_cfg.pri_ch);
1680 if (ret_val) {
1681 hddLog(LOGE,
1682 FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail"));
1683 kfree_skb(vendor_event);
1684 return;
1685 }
1686
1687 ret_val = nla_put_u8(vendor_event,
1688 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1689 sap_cfg->acs_cfg.ht_sec_ch);
1690 if (ret_val) {
1691 hddLog(LOGE,
1692 FL(
1693 "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail"));
1694 kfree_skb(vendor_event);
1695 return;
1696 }
1697
1698 ret_val = nla_put_u8(vendor_event,
1699 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1700 sap_cfg->acs_cfg.vht_seg0_center_ch);
1701 if (ret_val) {
1702 hddLog(LOGE,
1703 FL(
1704 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail"));
1705 kfree_skb(vendor_event);
1706 return;
1707 }
1708
1709 ret_val = nla_put_u8(vendor_event,
1710 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1711 sap_cfg->acs_cfg.vht_seg1_center_ch);
1712 if (ret_val) {
1713 hddLog(LOGE,
1714 FL(
1715 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail"));
1716 kfree_skb(vendor_event);
1717 return;
1718 }
1719
1720 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1721 ch_width = 80;
1722 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1723 ch_width = 40;
1724 else
1725 ch_width = 20;
1726
1727 ret_val = nla_put_u16(vendor_event,
1728 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1729 ch_width);
1730 if (ret_val) {
1731 hddLog(LOGE,
1732 FL(
1733 "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail"));
1734 kfree_skb(vendor_event);
1735 return;
1736 }
1737 if (sap_cfg->acs_cfg.pri_ch > 14)
1738 ret_val = nla_put_u8(vendor_event,
1739 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1740 QCA_ACS_MODE_IEEE80211A);
1741 else
1742 ret_val = nla_put_u8(vendor_event,
1743 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1744 QCA_ACS_MODE_IEEE80211G);
1745
1746 if (ret_val) {
1747 hddLog(LOGE,
1748 FL(
1749 "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail"));
1750 kfree_skb(vendor_event);
1751 return;
1752 }
1753
1754 hddLog(LOG1,
1755 FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"),
1756 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1757 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1758 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1759
1760 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1761 /* ***Note*** As already mentioned Completion variable usage is not
1762 * allowed here since ACS scan operation may take max 2.2 sec.
1763 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1764 * operation.
1765 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1766 * when Primary AP ACS is complete and secondary AP ACS is started here
1767 * immediately, Primary AP start_bss may come inbetween ACS operation
1768 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1769 * delay. This path and below constraint will be removed on sessionizing
1770 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1771 * As per design constraint user space control application must take
1772 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1773 * this code path. Sec AP hostapd should be started after Primary AP
1774 * start beaconing which can be confirmed by getchannel iwpriv command
1775 */
1776
1777 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1778 if (con_sap_adapter &&
1779 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
1780#ifdef CONFIG_CNSS
1781 cnss_init_delayed_work(&con_sap_adapter->acs_pending_work,
1782 wlan_hdd_cfg80211_start_pending_acs);
1783#else
1784 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1785 wlan_hdd_cfg80211_start_pending_acs);
1786#endif
1787 /* Lets give 500ms for OBSS + START_BSS to complete */
1788 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1789 msecs_to_jiffies(500));
1790 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1791 }
1792
1793 return;
1794}
1795
1796static int
1797__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1798 struct wireless_dev *wdev,
1799 const void *data,
1800 int data_len)
1801{
1802 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1803 struct sk_buff *skb = NULL;
1804 uint32_t fset = 0;
1805 int ret;
1806
Jeff Johnson1f61b612016-02-12 16:28:33 -08001807 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301808
Anurag Chouhan6d760662016-02-20 16:05:43 +05301809 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 hdd_err("Command not allowed in FTM mode");
1811 return -EPERM;
1812 }
1813
1814 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301815 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817
1818 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
1819 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
1820 fset |= WIFI_FEATURE_INFRA;
1821 }
1822 if (true == hdd_is_5g_supported(pHddCtx)) {
1823 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
1824 fset |= WIFI_FEATURE_INFRA_5G;
1825 }
1826#ifdef WLAN_FEATURE_P2P
1827 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1828 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
1829 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
1830 fset |= WIFI_FEATURE_P2P;
1831 }
1832#endif
1833 fset |= WIFI_FEATURE_SOFT_AP;
1834
1835 /* HOTSPOT is a supplicant feature, enable it by default */
1836 fset |= WIFI_FEATURE_HOTSPOT;
1837
1838#ifdef FEATURE_WLAN_EXTSCAN
1839 if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
1840 hddLog(LOG1, FL("EXTScan is supported by firmware"));
1841 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1842 }
1843#endif
1844 if (wlan_hdd_nan_is_supported()) {
1845 hddLog(LOG1, FL("NAN is supported by firmware"));
1846 fset |= WIFI_FEATURE_NAN;
1847 }
1848 if (sme_is_feature_supported_by_fw(RTT)) {
1849 hddLog(LOG1, FL("RTT is supported by firmware"));
1850 fset |= WIFI_FEATURE_D2D_RTT;
1851 fset |= WIFI_FEATURE_D2AP_RTT;
1852 }
1853#ifdef FEATURE_WLAN_SCAN_PNO
1854 if (pHddCtx->config->configPNOScanSupport &&
1855 sme_is_feature_supported_by_fw(PNO)) {
1856 hddLog(LOG1, FL("PNO is supported by firmware"));
1857 fset |= WIFI_FEATURE_PNO;
1858 }
1859#endif
1860 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1861#ifdef FEATURE_WLAN_TDLS
1862 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1863 sme_is_feature_supported_by_fw(TDLS)) {
1864 hddLog(LOG1, FL("TDLS is supported by firmware"));
1865 fset |= WIFI_FEATURE_TDLS;
1866 }
1867 if (sme_is_feature_supported_by_fw(TDLS) &&
1868 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1869 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
1870 hddLog(LOG1, FL("TDLS off-channel is supported by firmware"));
1871 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1872 }
1873#endif
1874#ifdef WLAN_AP_STA_CONCURRENCY
1875 fset |= WIFI_FEATURE_AP_STA;
1876#endif
1877 fset |= WIFI_FEATURE_RSSI_MONITOR;
1878
1879 if (hdd_link_layer_stats_supported())
1880 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1881
1882 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1883 NLMSG_HDRLEN);
1884 if (!skb) {
1885 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1886 return -EINVAL;
1887 }
1888 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
1889 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
1890 hddLog(LOGE, FL("nla put fail"));
1891 goto nla_put_failure;
1892 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301893 ret = cfg80211_vendor_cmd_reply(skb);
1894 EXIT();
1895 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896nla_put_failure:
1897 kfree_skb(skb);
1898 return -EINVAL;
1899}
1900
1901/**
1902 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1903 * @wiphy: pointer to wireless wiphy structure.
1904 * @wdev: pointer to wireless_dev structure.
1905 * @data: Pointer to the data to be passed via vendor interface
1906 * @data_len:Length of the data to be passed
1907 *
1908 * Return: Return the Success or Failure code.
1909 */
1910static int
1911wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1912 struct wireless_dev *wdev,
1913 const void *data, int data_len)
1914{
1915 int ret = 0;
1916
1917 cds_ssr_protect(__func__);
1918 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1919 data, data_len);
1920 cds_ssr_unprotect(__func__);
1921
1922 return ret;
1923}
1924
1925/**
1926 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1927 * @wiphy: pointer to wireless wiphy structure.
1928 * @wdev: pointer to wireless_dev structure.
1929 * @data: Pointer to the data to be passed via vendor interface
1930 * @data_len:Length of the data to be passed
1931 *
1932 * Set the MAC address that is to be used for scanning.
1933 *
1934 * Return: Return the Success or Failure code.
1935 */
1936static int
1937__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1938 struct wireless_dev *wdev,
1939 const void *data,
1940 int data_len)
1941{
1942 tpSirScanMacOui pReqMsg = NULL;
1943 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1944 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301945 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 int ret;
1947
Jeff Johnson1f61b612016-02-12 16:28:33 -08001948 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949
Anurag Chouhan6d760662016-02-20 16:05:43 +05301950 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 hdd_err("Command not allowed in FTM mode");
1952 return -EPERM;
1953 }
1954
1955 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301956 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958
1959 if (false == pHddCtx->config->enable_mac_spoofing) {
1960 hddLog(LOGW, FL("MAC address spoofing is not enabled"));
1961 return -ENOTSUPP;
1962 }
1963
1964 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1965 data, data_len, NULL)) {
1966 hddLog(LOGE, FL("Invalid ATTR"));
1967 return -EINVAL;
1968 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301969 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970 if (!pReqMsg) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301971 hddLog(LOGE, FL("qdf_mem_malloc failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 return -ENOMEM;
1973 }
1974 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
1975 hddLog(LOGE, FL("attr mac oui failed"));
1976 goto fail;
1977 }
1978 nla_memcpy(&pReqMsg->oui[0],
1979 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1980 sizeof(pReqMsg->oui));
1981 hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0],
1982 pReqMsg->oui[1], pReqMsg->oui[2]);
1983 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301984 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301985 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 FL("sme_set_scanning_mac_oui failed(err=%d)"), status);
1987 goto fail;
1988 }
1989 return 0;
1990fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301991 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 return -EINVAL;
1993}
1994
1995/**
1996 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1997 * @wiphy: pointer to wireless wiphy structure.
1998 * @wdev: pointer to wireless_dev structure.
1999 * @data: Pointer to the data to be passed via vendor interface
2000 * @data_len:Length of the data to be passed
2001 *
2002 * Set the MAC address that is to be used for scanning. This is an
2003 * SSR-protecting wrapper function.
2004 *
2005 * Return: Return the Success or Failure code.
2006 */
2007static int
2008wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2009 struct wireless_dev *wdev,
2010 const void *data,
2011 int data_len)
2012{
2013 int ret;
2014
2015 cds_ssr_protect(__func__);
2016 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2017 data, data_len);
2018 cds_ssr_unprotect(__func__);
2019
2020 return ret;
2021}
2022
2023/**
2024 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2025 * @feature_flags: pointer to the byte array of features.
2026 * @feature: Feature to be turned ON in the byte array.
2027 *
2028 * Return: None
2029 *
2030 * This is called to turn ON or SET the feature flag for the requested feature.
2031 **/
2032#define NUM_BITS_IN_BYTE 8
2033void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2034{
2035 uint32_t index;
2036 uint8_t bit_mask;
2037
2038 index = feature / NUM_BITS_IN_BYTE;
2039 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2040 feature_flags[index] |= bit_mask;
2041}
2042
2043/**
2044 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2045 * @wiphy: pointer to wireless wiphy structure.
2046 * @wdev: pointer to wireless_dev structure.
2047 * @data: Pointer to the data to be passed via vendor interface
2048 * @data_len:Length of the data to be passed
2049 *
2050 * This is called when wlan driver needs to send supported feature set to
2051 * supplicant upon a request/query from the supplicant.
2052 *
2053 * Return: Return the Success or Failure code.
2054 **/
2055#define MAX_CONCURRENT_CHAN_ON_24G 2
2056#define MAX_CONCURRENT_CHAN_ON_5G 2
2057static int
2058__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2059 struct wireless_dev *wdev,
2060 const void *data, int data_len)
2061{
2062 struct sk_buff *skb = NULL;
2063 uint32_t dbs_capability = 0;
2064 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302065 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 int ret_val;
2067
2068 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2069 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2070
Jeff Johnson1f61b612016-02-12 16:28:33 -08002071 ENTER_DEV(wdev->netdev);
2072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002073 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2074 if (ret_val)
2075 return ret_val;
2076
Anurag Chouhan6d760662016-02-20 16:05:43 +05302077 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 hdd_err("Command not allowed in FTM mode");
2079 return -EPERM;
2080 }
2081
2082 if (hdd_ctx_ptr->config->isRoamOffloadEnabled) {
2083 hddLog(LOG1, FL("Key Mgmt Offload is supported"));
2084 wlan_hdd_cfg80211_set_feature(feature_flags,
2085 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2086 }
2087
2088 wlan_hdd_cfg80211_set_feature(feature_flags,
2089 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2090 if (wma_is_scan_simultaneous_capable())
2091 wlan_hdd_cfg80211_set_feature(feature_flags,
2092 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
2093 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2094 NLMSG_HDRLEN);
2095
2096 if (!skb) {
2097 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2098 return -ENOMEM;
2099 }
2100
2101 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2102 sizeof(feature_flags), feature_flags))
2103 goto nla_put_failure;
2104
2105 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302106 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 if (one_by_one_dbs)
2108 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2109
2110 if (two_by_two_dbs)
2111 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2112
2113 if (!one_by_one_dbs && !two_by_two_dbs)
2114 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2115 } else {
2116 hdd_err("wma_get_dbs_hw_mode failed");
2117 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2118 }
2119
2120 hdd_info("dbs_capability is %d", dbs_capability);
2121
2122 if (nla_put_u32(skb,
2123 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2124 MAX_CONCURRENT_CHAN_ON_24G))
2125 goto nla_put_failure;
2126
2127 if (nla_put_u32(skb,
2128 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2129 MAX_CONCURRENT_CHAN_ON_5G))
2130 goto nla_put_failure;
2131
2132 return cfg80211_vendor_cmd_reply(skb);
2133
2134nla_put_failure:
2135 kfree_skb(skb);
2136 return -EINVAL;
2137}
2138
2139/**
2140 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2141 * @wiphy: pointer to wireless wiphy structure.
2142 * @wdev: pointer to wireless_dev structure.
2143 * @data: Pointer to the data to be passed via vendor interface
2144 * @data_len:Length of the data to be passed
2145 *
2146 * This is called when wlan driver needs to send supported feature set to
2147 * supplicant upon a request/query from the supplicant.
2148 *
2149 * Return: Return the Success or Failure code.
2150 */
2151static int
2152wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2153 struct wireless_dev *wdev,
2154 const void *data, int data_len)
2155{
2156 int ret;
2157
2158 cds_ssr_protect(__func__);
2159 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2160 data, data_len);
2161 cds_ssr_unprotect(__func__);
2162
2163 return ret;
2164}
2165
2166
2167/**
2168 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2169 * @wiphy: The wiphy structure
2170 * @wdev: The wireless device
2171 * @data: Data passed by framework
2172 * @data_len: Parameters to be configured passed as data
2173 *
2174 * The roaming related parameters are configured by the framework
2175 * using this interface.
2176 *
2177 * Return: Return either success or failure code.
2178 */
2179static int
2180__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2181 struct wireless_dev *wdev, const void *data, int data_len)
2182{
2183 struct net_device *dev = wdev->netdev;
2184 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2185 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2186 uint8_t session_id;
2187 struct roam_ext_params roam_params;
2188 uint32_t cmd_type, req_id;
2189 struct nlattr *curr_attr;
2190 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2191 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2192 int rem, i;
2193 uint32_t buf_len = 0;
2194 int ret;
2195
Jeff Johnson1f61b612016-02-12 16:28:33 -08002196 ENTER_DEV(dev);
2197
Anurag Chouhan6d760662016-02-20 16:05:43 +05302198 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002199 hdd_err("Command not allowed in FTM mode");
2200 return -EPERM;
2201 }
2202
2203 ret = wlan_hdd_validate_context(pHddCtx);
2204 if (0 != ret) {
2205 hddLog(LOGE, FL("HDD context is not valid"));
2206 return -EINVAL;
2207 }
2208
2209 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2210 data, data_len,
2211 NULL)) {
2212 hddLog(LOGE, FL("Invalid ATTR"));
2213 return -EINVAL;
2214 }
2215 /* Parse and fetch Command Type*/
2216 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
2217 hddLog(LOGE, FL("roam cmd type failed"));
2218 goto fail;
2219 }
2220 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302221 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2223 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
2224 hddLog(LOGE, FL("attr request id failed"));
2225 goto fail;
2226 }
2227 req_id = nla_get_u32(
2228 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302229 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id);
2230 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002231 switch (cmd_type) {
2232 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2233 i = 0;
2234 nla_for_each_nested(curr_attr,
2235 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2236 rem) {
2237 if (nla_parse(tb2,
2238 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2239 nla_data(curr_attr), nla_len(curr_attr),
2240 NULL)) {
2241 hddLog(LOGE,
2242 FL("nla_parse failed"));
2243 goto fail;
2244 }
2245 /* Parse and Fetch allowed SSID list*/
2246 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
2247 hddLog(LOGE, FL("attr allowed ssid failed"));
2248 goto fail;
2249 }
2250 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2251 /*
2252 * Upper Layers include a null termination character.
2253 * Check for the actual permissible length of SSID and
2254 * also ensure not to copy the NULL termination
2255 * character to the driver buffer.
2256 */
2257 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2258 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2259 nla_memcpy(
2260 roam_params.ssid_allowed_list[i].ssId,
2261 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2262 buf_len - 1);
2263 roam_params.ssid_allowed_list[i].length =
2264 buf_len - 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302265 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002266 FL("SSID[%d]: %.*s,length = %d"), i,
2267 roam_params.ssid_allowed_list[i].length,
2268 roam_params.ssid_allowed_list[i].ssId,
2269 roam_params.ssid_allowed_list[i].length);
2270 i++;
2271 } else {
2272 hddLog(LOGE, FL("Invalid buffer length"));
2273 }
2274 }
2275 roam_params.num_ssid_allowed_list = i;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302276 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 roam_params.num_ssid_allowed_list);
2278 sme_update_roam_params(pHddCtx->hHal, session_id,
2279 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2280 break;
2281 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2282 /* Parse and fetch 5G Boost Threshold */
2283 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
2284 hddLog(LOGE, FL("5G boost threshold failed"));
2285 goto fail;
2286 }
2287 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2288 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302289 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 roam_params.raise_rssi_thresh_5g);
2291 /* Parse and fetch 5G Penalty Threshold */
2292 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
2293 hddLog(LOGE, FL("5G penalty threshold failed"));
2294 goto fail;
2295 }
2296 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2297 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302298 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002299 roam_params.drop_rssi_thresh_5g);
2300 /* Parse and fetch 5G Boost Factor */
2301 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
2302 hddLog(LOGE, FL("5G boost Factor failed"));
2303 goto fail;
2304 }
2305 roam_params.raise_factor_5g = nla_get_u32(
2306 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302307 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 roam_params.raise_factor_5g);
2309 /* Parse and fetch 5G Penalty factor */
2310 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
2311 hddLog(LOGE, FL("5G Penalty Factor failed"));
2312 goto fail;
2313 }
2314 roam_params.drop_factor_5g = nla_get_u32(
2315 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302316 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 roam_params.drop_factor_5g);
2318 /* Parse and fetch 5G Max Boost */
2319 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
2320 hddLog(LOGE, FL("5G Max Boost failed"));
2321 goto fail;
2322 }
2323 roam_params.max_raise_rssi_5g = nla_get_u32(
2324 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302325 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 roam_params.max_raise_rssi_5g);
2327 /* Parse and fetch Rssi Diff */
2328 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
2329 hddLog(LOGE, FL("Rssi Diff failed"));
2330 goto fail;
2331 }
2332 roam_params.rssi_diff = nla_get_s32(
2333 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302334 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 roam_params.rssi_diff);
2336 /* Parse and fetch Alert Rssi Threshold */
2337 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
2338 hddLog(LOGE, FL("Alert Rssi Threshold failed"));
2339 goto fail;
2340 }
2341 roam_params.alert_rssi_threshold = nla_get_u32(
2342 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302343 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Alert RSSI Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 roam_params.alert_rssi_threshold);
2345 sme_update_roam_params(pHddCtx->hHal, session_id,
2346 roam_params,
2347 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2348 break;
2349 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2350 /* Parse and fetch Activate Good Rssi Roam */
2351 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
2352 hddLog(LOGE, FL("Activate Good Rssi Roam failed"));
2353 goto fail;
2354 }
2355 roam_params.good_rssi_roam = nla_get_s32(
2356 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302357 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Activate Good Rssi Roam (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358 roam_params.good_rssi_roam);
2359 sme_update_roam_params(pHddCtx->hHal, session_id,
2360 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2361 break;
2362 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2363 /* Parse and fetch number of preferred BSSID */
2364 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
2365 hddLog(LOGE, FL("attr num of preferred bssid failed"));
2366 goto fail;
2367 }
2368 roam_params.num_bssid_favored = nla_get_u32(
2369 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302370 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Preferred BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 roam_params.num_bssid_favored);
2372 i = 0;
2373 nla_for_each_nested(curr_attr,
2374 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2375 rem) {
2376 if (nla_parse(tb2,
2377 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2378 nla_data(curr_attr), nla_len(curr_attr),
2379 NULL)) {
2380 hddLog(LOGE, FL("nla_parse failed"));
2381 goto fail;
2382 }
2383 /* Parse and fetch MAC address */
2384 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
2385 hddLog(LOGE, FL("attr mac address failed"));
2386 goto fail;
2387 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002388 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302390 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002391 hdd_debug(MAC_ADDRESS_STR,
2392 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 /* Parse and fetch preference factor*/
2394 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
2395 hddLog(LOGE, FL("BSSID Preference score failed"));
2396 goto fail;
2397 }
2398 roam_params.bssid_favored_factor[i] = nla_get_u32(
2399 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302400 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("BSSID Preference score (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 roam_params.bssid_favored_factor[i]);
2402 i++;
2403 }
2404 sme_update_roam_params(pHddCtx->hHal, session_id,
2405 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2406 break;
2407 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2408 /* Parse and fetch number of blacklist BSSID */
2409 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
2410 hddLog(LOGE, FL("attr num of blacklist bssid failed"));
2411 goto fail;
2412 }
2413 roam_params.num_bssid_avoid_list = nla_get_u32(
2414 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302415 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of blacklist BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416 roam_params.num_bssid_avoid_list);
2417 i = 0;
2418 nla_for_each_nested(curr_attr,
2419 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2420 rem) {
2421 if (nla_parse(tb2,
2422 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2423 nla_data(curr_attr), nla_len(curr_attr),
2424 NULL)) {
2425 hddLog(LOGE, FL("nla_parse failed"));
2426 goto fail;
2427 }
2428 /* Parse and fetch MAC address */
2429 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
2430 hddLog(LOGE, FL("attr blacklist addr failed"));
2431 goto fail;
2432 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002433 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302435 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002436 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002438 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 i++;
2440 }
2441 sme_update_roam_params(pHddCtx->hHal, session_id,
2442 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2443 break;
2444 }
2445 return 0;
2446fail:
2447 return -EINVAL;
2448}
2449
2450/**
2451 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2452 * @wiphy: pointer to wireless wiphy structure.
2453 * @wdev: pointer to wireless_dev structure.
2454 * @data: Pointer to the data to be passed via vendor interface
2455 * @data_len:Length of the data to be passed
2456 *
2457 * Return: Return the Success or Failure code.
2458 */
2459static int
2460wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2461 struct wireless_dev *wdev,
2462 const void *data,
2463 int data_len)
2464{
2465 int ret;
2466
2467 cds_ssr_protect(__func__);
2468 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2469 data, data_len);
2470 cds_ssr_unprotect(__func__);
2471
2472 return ret;
2473}
2474
2475static const struct nla_policy
2476wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2477 +1] = {
2478 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2479};
2480
2481/**
2482 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2483 * @hdd_ctx: HDD context
2484 * @device_mode: device mode
2485 * Return: bool
2486 */
2487static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
2488 device_mode_t device_mode)
2489{
2490 hdd_adapter_t *adapter;
2491 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2492 hdd_ap_ctx_t *ap_ctx;
2493 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302494 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302496 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 &adapter_node);
2498
2499 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302500 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501 adapter = adapter_node->pAdapter;
2502
2503 if ((device_mode == adapter->device_mode) &&
2504 (device_mode == WLAN_HDD_SOFTAP)) {
2505 ap_ctx =
2506 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2507
2508 /*
2509 * if there is SAP already running on DFS channel,
2510 * do not disable scan on dfs channels. Note that
2511 * with SAP on DFS, there cannot be conurrency on
2512 * single radio. But then we can have multiple
2513 * radios !!
2514 */
2515 if (CHANNEL_STATE_DFS ==
2516 cds_get_channel_state(
2517 ap_ctx->operatingChannel)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302518 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 FL("SAP running on DFS channel"));
2520 return true;
2521 }
2522 }
2523
2524 if ((device_mode == adapter->device_mode) &&
2525 (device_mode == WLAN_HDD_INFRA_STATION)) {
2526 sta_ctx =
2527 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2528
2529 /*
2530 * if STA is already connected on DFS channel,
2531 * do not disable scan on dfs channels
2532 */
2533 if (hdd_conn_is_connected(sta_ctx) &&
2534 (CHANNEL_STATE_DFS ==
2535 cds_get_channel_state(
2536 sta_ctx->conn_info.operationChannel))) {
2537 hddLog(LOGE,
2538 FL("client connected on DFS channel"));
2539 return true;
2540 }
2541 }
2542
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302543 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 adapter_node,
2545 &next);
2546 adapter_node = next;
2547 }
2548
2549 return false;
2550}
2551
2552/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002553 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2554 * @hdd_ctx: HDD context within host driver
2555 * @adapter: Adapter pointer
2556 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2557 *
2558 * Loops through devices to see who is operating on DFS channels
2559 * and then disables/enables DFS channels by calling SME API.
2560 * Fails the disable request if any device is active on a DFS channel.
2561 *
2562 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002564
2565int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2566 hdd_adapter_t *adapter,
2567 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302570 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572
2573 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2574 if (no_dfs_flag) {
2575 status = wlan_hdd_check_dfs_channel_for_adapter(
2576 hdd_ctx, WLAN_HDD_INFRA_STATION);
2577
2578 if (true == status)
2579 return -EOPNOTSUPP;
2580
2581 status = wlan_hdd_check_dfs_channel_for_adapter(
2582 hdd_ctx, WLAN_HDD_SOFTAP);
2583
2584 if (true == status)
2585 return -EOPNOTSUPP;
2586 }
2587
2588 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2589
2590 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2591
2592 /*
2593 * call the SME API to tunnel down the new channel list
2594 * to the firmware
2595 */
2596 status = sme_handle_dfs_chan_scan(
2597 h_hal, hdd_ctx->config->enableDFSChnlScan);
2598
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302599 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 ret_val = 0;
2601
2602 /*
2603 * Clear the SME scan cache also. Note that the
2604 * clearing of scan results is independent of session;
2605 * so no need to iterate over
2606 * all sessions
2607 */
2608 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302609 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 ret_val = -EPERM;
2611 }
2612
2613 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302614 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 FL(" the DFS flag has not changed"));
2616 ret_val = 0;
2617 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002618 return ret_val;
2619}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002621/**
2622 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2623 * @wiphy: corestack handler
2624 * @wdev: wireless device
2625 * @data: data
2626 * @data_len: data length
2627 * Return: success(0) or reason code for failure
2628 */
2629static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2630 struct wireless_dev *wdev,
2631 const void *data,
2632 int data_len)
2633{
2634 struct net_device *dev = wdev->netdev;
2635 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2636 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2637 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2638 int ret_val;
2639 uint32_t no_dfs_flag = 0;
2640
Jeff Johnson1f61b612016-02-12 16:28:33 -08002641 ENTER_DEV(dev);
2642
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002643 ret_val = wlan_hdd_validate_context(hdd_ctx);
2644
2645 if (ret_val) {
2646 hdd_err("HDD context is not valid");
2647 return ret_val;
2648 }
2649
2650 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2651 data, data_len,
2652 wlan_hdd_set_no_dfs_flag_config_policy)) {
2653 hdd_err("invalid attr");
2654 return -EINVAL;
2655 }
2656
2657 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2658 hdd_err("attr dfs flag failed");
2659 return -EINVAL;
2660 }
2661
2662 no_dfs_flag = nla_get_u32(
2663 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2664
2665 hddLog(LOG1, FL(" DFS flag = %d"), no_dfs_flag);
2666
2667 if (no_dfs_flag > 1) {
2668 hddLog(LOGE, FL("invalid value of dfs flag"));
2669 return -EINVAL;
2670 }
2671
2672 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2673 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 return ret_val;
2675}
2676
2677/**
2678 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2679 *
2680 * @wiphy: wiphy device pointer
2681 * @wdev: wireless device pointer
2682 * @data: Vendof command data buffer
2683 * @data_len: Buffer length
2684 *
2685 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2686 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2687 *
2688 * Return: EOK or other error codes.
2689 */
2690
2691static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2692 struct wireless_dev *wdev,
2693 const void *data,
2694 int data_len)
2695{
2696 int ret;
2697
2698 cds_ssr_protect(__func__);
2699 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2700 data, data_len);
2701 cds_ssr_unprotect(__func__);
2702
2703 return ret;
2704}
2705
2706#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2707/**
2708 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2709 * @wiphy: pointer to wireless wiphy structure.
2710 * @wdev: pointer to wireless_dev structure.
2711 * @data: Pointer to the Key data
2712 * @data_len:Length of the data passed
2713 *
2714 * This is called when wlan driver needs to save the keys received via
2715 * vendor specific command.
2716 *
2717 * Return: Return the Success or Failure code.
2718 */
2719static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2720 struct wireless_dev *wdev,
2721 const void *data, int data_len)
2722{
2723 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
2724 struct net_device *dev = wdev->netdev;
2725 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
2726 hdd_context_t *hdd_ctx_ptr;
2727 int status;
2728
Jeff Johnson1f61b612016-02-12 16:28:33 -08002729 ENTER_DEV(dev);
2730
Anurag Chouhan6d760662016-02-20 16:05:43 +05302731 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732 hdd_err("Command not allowed in FTM mode");
2733 return -EPERM;
2734 }
2735
2736 if ((data == NULL) || (data_len == 0) ||
2737 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
2738 hddLog(LOGE, FL("Invalid data"));
2739 return -EINVAL;
2740 }
2741
2742 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
2743 if (!hdd_ctx_ptr) {
2744 hddLog(LOGE, FL("HDD context is null"));
2745 return -EINVAL;
2746 }
2747
2748 status = wlan_hdd_validate_context(hdd_ctx_ptr);
2749 if (0 != status) {
2750 hddLog(LOGE, FL("HDD context is invalid"));
2751 return status;
2752 }
2753 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
2754 hdd_adapter_ptr->sessionId,
2755 true);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302756 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
2757 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
2759 hdd_adapter_ptr->sessionId, local_pmk, data_len);
2760 return 0;
2761}
2762
2763/**
2764 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2765 * @wiphy: pointer to wireless wiphy structure.
2766 * @wdev: pointer to wireless_dev structure.
2767 * @data: Pointer to the Key data
2768 * @data_len:Length of the data passed
2769 *
2770 * This is called when wlan driver needs to save the keys received via
2771 * vendor specific command.
2772 *
2773 * Return: Return the Success or Failure code.
2774 */
2775static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2776 struct wireless_dev *wdev,
2777 const void *data, int data_len)
2778{
2779 int ret;
2780
2781 cds_ssr_protect(__func__);
2782 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
2783 cds_ssr_unprotect(__func__);
2784
2785 return ret;
2786}
2787
2788static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
2789 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
2790 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
2791 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
2792};
2793
2794/**
2795 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2796 * @wiphy: pointer to wireless wiphy structure.
2797 * @wdev: pointer to wireless_dev structure.
2798 * @data: Pointer to the data to be passed via vendor interface
2799 * @data_len:Length of the data to be passed
2800 *
2801 * This is called when wlan driver needs to send wifi driver related info
2802 * (driver/fw version) to the user space application upon request.
2803 *
2804 * Return: Return the Success or Failure code.
2805 */
2806static int
2807__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2808 struct wireless_dev *wdev,
2809 const void *data, int data_len)
2810{
2811 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2812 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
2813 tSirVersionString version;
2814 uint32_t version_len;
2815 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
2816 uint8_t attr;
2817 int status;
2818 struct sk_buff *reply_skb = NULL;
2819
Jeff Johnson1f61b612016-02-12 16:28:33 -08002820 ENTER_DEV(wdev->netdev);
2821
Anurag Chouhan6d760662016-02-20 16:05:43 +05302822 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 hdd_err("Command not allowed in FTM mode");
2824 return -EPERM;
2825 }
2826
2827 status = wlan_hdd_validate_context(hdd_ctx);
2828 if (0 != status) {
2829 hddLog(LOGE, FL("HDD context is not valid"));
2830 return -EINVAL;
2831 }
2832
2833 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
2834 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
2835 hddLog(LOGE, FL("WIFI_INFO_GET NL CMD parsing failed"));
2836 return -EINVAL;
2837 }
2838
2839 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
2840 hddLog(LOG1, FL("Rcvd req for Driver version"));
2841 strlcpy(version, QWLAN_VERSIONSTR, sizeof(version));
2842 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
2843 } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
2844 hddLog(LOG1, FL("Rcvd req for FW version"));
2845 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
2846 &crmid);
2847 snprintf(version, sizeof(version), "%d:%d:%d:%d",
2848 major_spid, minor_spid, siid, crmid);
2849 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
2850 } else {
2851 hddLog(LOGE, FL("Invalid attribute in get wifi info request"));
2852 return -EINVAL;
2853 }
2854
2855 version_len = strlen(version);
2856 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2857 version_len + NLA_HDRLEN + NLMSG_HDRLEN);
2858 if (!reply_skb) {
2859 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2860 return -ENOMEM;
2861 }
2862
2863 if (nla_put(reply_skb, attr, version_len, version)) {
2864 hddLog(LOGE, FL("nla put fail"));
2865 kfree_skb(reply_skb);
2866 return -EINVAL;
2867 }
2868
2869 return cfg80211_vendor_cmd_reply(reply_skb);
2870}
2871
2872/**
2873 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2874 * @wiphy: pointer to wireless wiphy structure.
2875 * @wdev: pointer to wireless_dev structure.
2876 * @data: Pointer to the data to be passed via vendor interface
2877 * @data_len:Length of the data to be passed
2878 *
2879 * This is called when wlan driver needs to send wifi driver related info
2880 * (driver/fw version) to the user space application upon request.
2881 *
2882 * Return: Return the Success or Failure code.
2883 */
2884static int
2885wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2886 struct wireless_dev *wdev,
2887 const void *data, int data_len)
2888{
2889 int ret;
2890
2891 cds_ssr_protect(__func__);
2892 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
2893 cds_ssr_unprotect(__func__);
2894
2895 return ret;
2896}
2897
2898/**
2899 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
2900 * @wiphy: pointer to wireless wiphy structure.
2901 * @wdev: pointer to wireless_dev structure.
2902 * @data: Pointer to the data to be passed via vendor interface
2903 * @data_len:Length of the data to be passed
2904 *
2905 * This is called by userspace to know the supported logger features
2906 *
2907 * Return: Return the Success or Failure code.
2908 */
2909static int
2910__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
2911 struct wireless_dev *wdev,
2912 const void *data, int data_len)
2913{
2914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2915 int status;
2916 uint32_t features;
2917 struct sk_buff *reply_skb = NULL;
2918
Jeff Johnson1f61b612016-02-12 16:28:33 -08002919 ENTER_DEV(wdev->netdev);
2920
Anurag Chouhan6d760662016-02-20 16:05:43 +05302921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 hdd_err("Command not allowed in FTM mode");
2923 return -EPERM;
2924 }
2925
2926 status = wlan_hdd_validate_context(hdd_ctx);
2927 if (0 != status) {
2928 hddLog(LOGE, FL("HDD context is not valid"));
2929 return -EINVAL;
2930 }
2931
2932 features = 0;
2933
2934 if (hdd_is_memdump_supported())
2935 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
2936 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
2937 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
2938 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
2939
2940 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2941 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
2942 if (!reply_skb) {
2943 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2944 return -ENOMEM;
2945 }
2946
2947 hddLog(LOG1, FL("Supported logger features: 0x%0x"), features);
2948 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
2949 features)) {
2950 hddLog(LOGE, FL("nla put fail"));
2951 kfree_skb(reply_skb);
2952 return -EINVAL;
2953 }
2954
2955 return cfg80211_vendor_cmd_reply(reply_skb);
2956}
2957
2958/**
2959 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
2960 * @wiphy: pointer to wireless wiphy structure.
2961 * @wdev: pointer to wireless_dev structure.
2962 * @data: Pointer to the data to be passed via vendor interface
2963 * @data_len:Length of the data to be passed
2964 *
2965 * This is called by userspace to know the supported logger features
2966 *
2967 * Return: Return the Success or Failure code.
2968 */
2969static int
2970wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
2971 struct wireless_dev *wdev,
2972 const void *data, int data_len)
2973{
2974 int ret;
2975
2976 cds_ssr_protect(__func__);
2977 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
2978 data, data_len);
2979 cds_ssr_unprotect(__func__);
2980
2981 return ret;
2982}
2983
2984/**
2985 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
2986 * @hdd_ctx_ptr: pointer to HDD Context.
2987 * @bssid: pointer to bssid of roamed AP.
2988 * @req_rsn_ie: Pointer to request RSN IE
2989 * @req_rsn_len: Length of the request RSN IE
2990 * @rsp_rsn_ie: Pointer to response RSN IE
2991 * @rsp_rsn_len: Length of the response RSN IE
2992 * @roam_info_ptr: Pointer to the roaming related information
2993 *
2994 * This is called when wlan driver needs to send the roaming and
2995 * authorization information after roaming.
2996 *
2997 * The information that would be sent is the request RSN IE, response
2998 * RSN IE and BSSID of the newly roamed AP.
2999 *
3000 * If the Authorized status is authenticated, then additional parameters
3001 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3002 * supplicant.
3003 *
3004 * The supplicant upon receiving this event would ignore the legacy
3005 * cfg80211_roamed call and use the entire information from this event.
3006 * The cfg80211_roamed should still co-exist since the kernel will
3007 * make use of the parameters even if the supplicant ignores it.
3008 *
3009 * Return: Return the Success or Failure code.
3010 */
3011int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3012 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3013 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3014{
3015 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003016 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 ENTER();
3018
3019 if (wlan_hdd_validate_context(hdd_ctx_ptr)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303020 hddLog(QDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid "));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 return -EINVAL;
3022 }
3023
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003024 if (!hdd_ctx_ptr->config->isRoamOffloadEnabled ||
3025 !roam_info_ptr->roamSynchInProgress)
3026 return 0;
3027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3029 NULL,
3030 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3031 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3032 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003033 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3035 GFP_KERNEL);
3036
3037 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303038 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003039 FL("cfg80211_vendor_event_alloc failed"));
3040 return -EINVAL;
3041 }
3042
3043 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3044 ETH_ALEN, bssid) ||
3045 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3046 req_rsn_len, req_rsn_ie) ||
3047 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3048 rsp_rsn_len, rsp_rsn_ie)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303049 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 goto nla_put_failure;
3051 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303052 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 roam_info_ptr->synchAuthStatus);
3054 if (roam_info_ptr->synchAuthStatus ==
3055 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303056 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's"));
Naveen Rawat14298b92015-11-25 16:27:41 -08003057 if (nla_put_u8(skb,
3058 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3059 hdd_err("nla put fail");
3060 goto nla_put_failure;
3061 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003062 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3063 /* if FT or CCKM connection: dont send replay counter */
3064 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3065 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3066 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3067 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3068 nla_put(skb,
3069 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3070 SIR_REPLAY_CTR_LEN,
3071 roam_info_ptr->replay_ctr)) {
3072 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003073 hdd_err("failed to send replay counter.");
3074 goto nla_put_failure;
3075 }
3076 if (nla_put(skb,
3077 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3078 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3079 nla_put(skb,
3080 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3081 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3082 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 goto nla_put_failure;
3084 }
3085 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303086 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3088 false)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303089 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090 goto nla_put_failure;
3091 }
3092 }
3093
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303094 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Subnet Change Status = %d"),
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003095 roam_info_ptr->subnet_change_status);
3096
3097 /*
3098 * Add subnet change status if subnet has changed
3099 * 0 = unchanged
3100 * 1 = changed
3101 * 2 = unknown
3102 */
3103 if (roam_info_ptr->subnet_change_status) {
3104 if (nla_put_u8(skb,
3105 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3106 roam_info_ptr->subnet_change_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303107 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003108 goto nla_put_failure;
3109 }
3110 }
3111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003112 cfg80211_vendor_event(skb, GFP_KERNEL);
3113 return 0;
3114
3115nla_put_failure:
3116 kfree_skb(skb);
3117 return -EINVAL;
3118}
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003119#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120
3121static const struct nla_policy
3122wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3123
3124 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3125 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3126 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3127};
3128
3129
3130/**
3131 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3132 * vendor command
3133 *
3134 * @wiphy: wiphy device pointer
3135 * @wdev: wireless device pointer
3136 * @data: Vendor command data buffer
3137 * @data_len: Buffer length
3138 *
3139 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3140 *
3141 * Return: Error code.
3142 */
3143static int
3144__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3145 struct wireless_dev *wdev,
3146 const void *data,
3147 int data_len)
3148{
3149 struct net_device *dev = wdev->netdev;
3150 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3151 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3152 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3153 int ret_val = 0;
3154 u32 modulated_dtim;
3155 u16 stats_avg_factor;
3156 u32 guard_time;
Krunal Sonie3531942016-04-12 17:43:53 -07003157 u32 ftm_capab;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303158 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159
Jeff Johnson1f61b612016-02-12 16:28:33 -08003160 ENTER_DEV(dev);
3161
Anurag Chouhan6d760662016-02-20 16:05:43 +05303162 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 hdd_err("Command not allowed in FTM mode");
3164 return -EPERM;
3165 }
3166
3167 ret_val = wlan_hdd_validate_context(hdd_ctx);
3168 if (ret_val) {
3169 hddLog(LOGE, FL("HDD context is not valid"));
3170 return ret_val;
3171 }
3172
3173 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3174 data, data_len,
3175 wlan_hdd_wifi_config_policy)) {
3176 hddLog(LOGE, FL("invalid attr"));
3177 return -EINVAL;
3178 }
3179
Krunal Sonie3531942016-04-12 17:43:53 -07003180 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3181 ftm_capab = nla_get_u32(tb[
3182 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3183 hdd_ctx->config->fine_time_meas_cap =
3184 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3185 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
3186 hdd_ctx->config->fine_time_meas_cap);
3187 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3188 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3189 hdd_ctx->config->fine_time_meas_cap);
3190 }
3191
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3193 modulated_dtim = nla_get_u32(
3194 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3195
3196 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3197 adapter->sessionId,
3198 modulated_dtim);
3199
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303200 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201 ret_val = -EPERM;
3202 }
3203
3204 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3205 stats_avg_factor = nla_get_u16(
3206 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3207 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3208 adapter->sessionId,
3209 stats_avg_factor);
3210
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303211 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 ret_val = -EPERM;
3213 }
3214
3215
3216 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3217 guard_time = nla_get_u32(
3218 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3219 status = sme_configure_guard_time(hdd_ctx->hHal,
3220 adapter->sessionId,
3221 guard_time);
3222
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303223 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 ret_val = -EPERM;
3225 }
3226
3227 return ret_val;
3228}
3229
3230/**
3231 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3232 * vendor command
3233 *
3234 * @wiphy: wiphy device pointer
3235 * @wdev: wireless device pointer
3236 * @data: Vendor command data buffer
3237 * @data_len: Buffer length
3238 *
3239 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3240 *
3241 * Return: EOK or other error codes.
3242 */
3243static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3244 struct wireless_dev *wdev,
3245 const void *data,
3246 int data_len)
3247{
3248 int ret;
3249
3250 cds_ssr_protect(__func__);
3251 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3252 data, data_len);
3253 cds_ssr_unprotect(__func__);
3254
3255 return ret;
3256}
3257
3258static const struct
3259nla_policy
3260qca_wlan_vendor_wifi_logger_start_policy
3261[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3262 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3263 = {.type = NLA_U32 },
3264 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3265 = {.type = NLA_U32 },
3266 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3267 = {.type = NLA_U32 },
3268};
3269
3270/**
3271 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3272 * or disable the collection of packet statistics from the firmware
3273 * @wiphy: WIPHY structure pointer
3274 * @wdev: Wireless device structure pointer
3275 * @data: Pointer to the data received
3276 * @data_len: Length of the data received
3277 *
3278 * This function enables or disables the collection of packet statistics from
3279 * the firmware
3280 *
3281 * Return: 0 on success and errno on failure
3282 */
3283static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3284 struct wireless_dev *wdev,
3285 const void *data,
3286 int data_len)
3287{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303288 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3290 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
3291 struct sir_wifi_start_log start_log;
3292
Jeff Johnson1f61b612016-02-12 16:28:33 -08003293 ENTER_DEV(wdev->netdev);
3294
Anurag Chouhan6d760662016-02-20 16:05:43 +05303295 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 hdd_err("Command not allowed in FTM mode");
3297 return -EPERM;
3298 }
3299
3300 status = wlan_hdd_validate_context(hdd_ctx);
3301 if (0 != status) {
3302 hddLog(LOGE, FL("HDD context is not valid"));
3303 return -EINVAL;
3304 }
3305
3306 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
3307 data, data_len,
3308 qca_wlan_vendor_wifi_logger_start_policy)) {
3309 hddLog(LOGE, FL("Invalid attribute"));
3310 return -EINVAL;
3311 }
3312
3313 /* Parse and fetch ring id */
3314 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
3315 hddLog(LOGE, FL("attr ATTR failed"));
3316 return -EINVAL;
3317 }
3318 start_log.ring_id = nla_get_u32(
3319 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003320 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321
3322 /* Parse and fetch verbose level */
3323 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
3324 hddLog(LOGE, FL("attr verbose_level failed"));
3325 return -EINVAL;
3326 }
3327 start_log.verbose_level = nla_get_u32(
3328 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003329 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003330
3331 /* Parse and fetch flag */
3332 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
3333 hddLog(LOGE, FL("attr flag failed"));
3334 return -EINVAL;
3335 }
3336 start_log.flag = nla_get_u32(
3337 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003338 hdd_info("flag=%d", start_log.flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339
3340 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
3341
3342 if (start_log.ring_id == RING_ID_WAKELOCK) {
3343 /* Start/stop wakelock events */
3344 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
3345 cds_set_wakelock_logging(true);
3346 else
3347 cds_set_wakelock_logging(false);
3348 return 0;
3349 }
3350
3351 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303352 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003353 hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"),
3354 status);
3355 return -EINVAL;
3356 }
3357 return 0;
3358}
3359
3360/**
3361 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
3362 * or disable the collection of packet statistics from the firmware
3363 * @wiphy: WIPHY structure pointer
3364 * @wdev: Wireless device structure pointer
3365 * @data: Pointer to the data received
3366 * @data_len: Length of the data received
3367 *
3368 * This function is used to enable or disable the collection of packet
3369 * statistics from the firmware
3370 *
3371 * Return: 0 on success and errno on failure
3372 */
3373static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3374 struct wireless_dev *wdev,
3375 const void *data,
3376 int data_len)
3377{
3378 int ret = 0;
3379
3380 cds_ssr_protect(__func__);
3381 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
3382 wdev, data, data_len);
3383 cds_ssr_unprotect(__func__);
3384
3385 return ret;
3386}
3387
3388static const struct
3389nla_policy
3390qca_wlan_vendor_wifi_logger_get_ring_data_policy
3391[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
3392 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
3393 = {.type = NLA_U32 },
3394};
3395
3396/**
3397 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
3398 * @wiphy: WIPHY structure pointer
3399 * @wdev: Wireless device structure pointer
3400 * @data: Pointer to the data received
3401 * @data_len: Length of the data received
3402 *
3403 * This function is used to flush or retrieve the per packet statistics from
3404 * the driver
3405 *
3406 * Return: 0 on success and errno on failure
3407 */
3408static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3409 struct wireless_dev *wdev,
3410 const void *data,
3411 int data_len)
3412{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303413 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414 uint32_t ring_id;
3415 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3416 struct nlattr *tb
3417 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
3418
Jeff Johnson1f61b612016-02-12 16:28:33 -08003419 ENTER_DEV(wdev->netdev);
3420
Anurag Chouhan6d760662016-02-20 16:05:43 +05303421 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 hdd_err("Command not allowed in FTM mode");
3423 return -EPERM;
3424 }
3425
3426 status = wlan_hdd_validate_context(hdd_ctx);
3427 if (0 != status) {
3428 hddLog(LOGE, FL("HDD context is not valid"));
3429 return -EINVAL;
3430 }
3431
3432 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
3433 data, data_len,
3434 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
3435 hddLog(LOGE, FL("Invalid attribute"));
3436 return -EINVAL;
3437 }
3438
3439 /* Parse and fetch ring id */
3440 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
3441 hddLog(LOGE, FL("attr ATTR failed"));
3442 return -EINVAL;
3443 }
3444
3445 ring_id = nla_get_u32(
3446 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
3447
3448 if (ring_id == RING_ID_PER_PACKET_STATS) {
3449 wlan_logging_set_per_pkt_stats();
3450 hddLog(LOG1, FL("Flushing/Retrieving packet stats"));
3451 }
3452
3453 hddLog(LOG1, FL("Bug report triggered by framework"));
3454
3455 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
3456 WLAN_LOG_INDICATOR_FRAMEWORK,
3457 WLAN_LOG_REASON_CODE_UNUSED);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303458 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 hddLog(LOGE, FL("Failed to trigger bug report"));
3460 return -EINVAL;
3461 }
3462
3463 return 0;
3464}
3465
3466/**
3467 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
3468 * @wiphy: WIPHY structure pointer
3469 * @wdev: Wireless device structure pointer
3470 * @data: Pointer to the data received
3471 * @data_len: Length of the data received
3472 *
3473 * This function is used to flush or retrieve the per packet statistics from
3474 * the driver
3475 *
3476 * Return: 0 on success and errno on failure
3477 */
3478static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3479 struct wireless_dev *wdev,
3480 const void *data,
3481 int data_len)
3482{
3483 int ret = 0;
3484
3485 cds_ssr_protect(__func__);
3486 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
3487 wdev, data, data_len);
3488 cds_ssr_unprotect(__func__);
3489
3490 return ret;
3491}
3492
3493#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
3494/**
3495 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
3496 * @hdd_ctx: HDD context
3497 * @request_id: [input] request id
3498 * @pattern_id: [output] pattern id
3499 *
3500 * This function loops through request id to pattern id array
3501 * if the slot is available, store the request id and return pattern id
3502 * if entry exists, return the pattern id
3503 *
3504 * Return: 0 on success and errno on failure
3505 */
3506static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3507 uint32_t request_id,
3508 uint8_t *pattern_id)
3509{
3510 uint32_t i;
3511
3512 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3513 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3514 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
3515 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
3516 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3517 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3518 return 0;
3519 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
3520 request_id) {
3521 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3522 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3523 return 0;
3524 }
3525 }
3526 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3527 return -EINVAL;
3528}
3529
3530/**
3531 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
3532 * @hdd_ctx: HDD context
3533 * @request_id: [input] request id
3534 * @pattern_id: [output] pattern id
3535 *
3536 * This function loops through request id to pattern id array
3537 * reset request id to 0 (slot available again) and
3538 * return pattern id
3539 *
3540 * Return: 0 on success and errno on failure
3541 */
3542static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3543 uint32_t request_id,
3544 uint8_t *pattern_id)
3545{
3546 uint32_t i;
3547
3548 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3549 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3550 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
3551 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
3552 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3553 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3554 return 0;
3555 }
3556 }
3557 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3558 return -EINVAL;
3559}
3560
3561
3562/*
3563 * define short names for the global vendor params
3564 * used by __wlan_hdd_cfg80211_offloaded_packets()
3565 */
3566#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
3567#define PARAM_REQUEST_ID \
3568 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
3569#define PARAM_CONTROL \
3570 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
3571#define PARAM_IP_PACKET \
3572 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
3573#define PARAM_SRC_MAC_ADDR \
3574 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
3575#define PARAM_DST_MAC_ADDR \
3576 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
3577#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
3578
3579/**
3580 * wlan_hdd_add_tx_ptrn() - add tx pattern
3581 * @adapter: adapter pointer
3582 * @hdd_ctx: hdd context
3583 * @tb: nl attributes
3584 *
3585 * This function reads the NL attributes and forms a AddTxPtrn message
3586 * posts it to SME.
3587 *
3588 */
3589static int
3590wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3591 struct nlattr **tb)
3592{
3593 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303594 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595 uint32_t request_id, ret, len;
3596 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303597 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 uint16_t eth_type = htons(ETH_P_IP);
3599
3600 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3601 hddLog(LOGE, FL("Not in Connected state!"));
3602 return -ENOTSUPP;
3603 }
3604
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303605 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003606 if (!add_req) {
3607 hddLog(LOGE, FL("memory allocation failed"));
3608 return -ENOMEM;
3609 }
3610
3611 /* Parse and fetch request Id */
3612 if (!tb[PARAM_REQUEST_ID]) {
3613 hddLog(LOGE, FL("attr request id failed"));
3614 goto fail;
3615 }
3616
3617 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3618 if (request_id == MAX_REQUEST_ID) {
3619 hddLog(LOGE, FL("request_id cannot be MAX"));
3620 return -EINVAL;
3621 }
3622 hddLog(LOG1, FL("Request Id: %u"), request_id);
3623
3624 if (!tb[PARAM_PERIOD]) {
3625 hddLog(LOGE, FL("attr period failed"));
3626 goto fail;
3627 }
3628 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
3629 hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs);
3630 if (add_req->usPtrnIntervalMs == 0) {
3631 hddLog(LOGE, FL("Invalid interval zero, return failure"));
3632 goto fail;
3633 }
3634
3635 if (!tb[PARAM_SRC_MAC_ADDR]) {
3636 hddLog(LOGE, FL("attr source mac address failed"));
3637 goto fail;
3638 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08003639 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303640 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003641 hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003642 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643
Anurag Chouhanc5548422016-02-24 18:33:27 +05303644 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003645 &adapter->macAddressCurrent)) {
3646 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003647 goto fail;
3648 }
3649
3650 if (!tb[PARAM_DST_MAC_ADDR]) {
3651 hddLog(LOGE, FL("attr dst mac address failed"));
3652 goto fail;
3653 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303654 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003655 hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR,
3656 MAC_ADDR_ARRAY(dst_addr.bytes));
3657
3658 if (!tb[PARAM_IP_PACKET]) {
3659 hddLog(LOGE, FL("attr ip packet failed"));
3660 goto fail;
3661 }
3662 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
3663 hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize);
3664
3665 if (add_req->ucPtrnSize < 0 ||
3666 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
3667 ETH_HLEN)) {
3668 hddLog(LOGE, FL("Invalid IP packet len: %d"),
3669 add_req->ucPtrnSize);
3670 goto fail;
3671 }
3672
3673 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303674 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303675 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303676 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303677 QDF_MAC_ADDR_SIZE);
3678 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303679 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680 len += 2;
3681
3682 /*
3683 * This is the IP packet, add 14 bytes Ethernet (802.3) header
3684 * ------------------------------------------------------------
3685 * | 14 bytes Ethernet (802.3) header | IP header and payload |
3686 * ------------------------------------------------------------
3687 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303688 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 nla_data(tb[PARAM_IP_PACKET]),
3690 add_req->ucPtrnSize);
3691 add_req->ucPtrnSize += len;
3692
3693 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3694 if (ret) {
3695 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3696 goto fail;
3697 }
3698 add_req->ucPtrnId = pattern_id;
3699 hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId);
3700
3701 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303702 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703 hddLog(LOGE,
3704 FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status);
3705 goto fail;
3706 }
3707
3708 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303709 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003710 return 0;
3711
3712fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303713 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003714 return -EINVAL;
3715}
3716
3717/**
3718 * wlan_hdd_del_tx_ptrn() - delete tx pattern
3719 * @adapter: adapter pointer
3720 * @hdd_ctx: hdd context
3721 * @tb: nl attributes
3722 *
3723 * This function reads the NL attributes and forms a DelTxPtrn message
3724 * posts it to SME.
3725 *
3726 */
3727static int
3728wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3729 struct nlattr **tb)
3730{
3731 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303732 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733 uint32_t request_id, ret;
3734 uint8_t pattern_id = 0;
3735
3736 /* Parse and fetch request Id */
3737 if (!tb[PARAM_REQUEST_ID]) {
3738 hddLog(LOGE, FL("attr request id failed"));
3739 return -EINVAL;
3740 }
3741 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3742 if (request_id == MAX_REQUEST_ID) {
3743 hddLog(LOGE, FL("request_id cannot be MAX"));
3744 return -EINVAL;
3745 }
3746
3747 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3748 if (ret) {
3749 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3750 return -EINVAL;
3751 }
3752
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303753 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003754 if (!del_req) {
3755 hddLog(LOGE, FL("memory allocation failed"));
3756 return -ENOMEM;
3757 }
3758
Anurag Chouhanc5548422016-02-24 18:33:27 +05303759 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08003760 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003761 del_req->ucPtrnId = pattern_id;
3762 hddLog(LOG1, FL("Request Id: %u Pattern id: %d"),
3763 request_id, del_req->ucPtrnId);
3764
3765 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303766 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767 hddLog(LOGE,
3768 FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status);
3769 goto fail;
3770 }
3771
3772 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303773 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 return 0;
3775
3776fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303777 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 return -EINVAL;
3779}
3780
3781
3782/**
3783 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
3784 * @wiphy: Pointer to wireless phy
3785 * @wdev: Pointer to wireless device
3786 * @data: Pointer to data
3787 * @data_len: Data length
3788 *
3789 * Return: 0 on success, negative errno on failure
3790 */
3791static int
3792__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3793 struct wireless_dev *wdev,
3794 const void *data,
3795 int data_len)
3796{
3797 struct net_device *dev = wdev->netdev;
3798 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3799 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3800 struct nlattr *tb[PARAM_MAX + 1];
3801 uint8_t control;
3802 int ret;
3803 static const struct nla_policy policy[PARAM_MAX + 1] = {
3804 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3805 [PARAM_CONTROL] = { .type = NLA_U32 },
3806 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303807 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303809 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 [PARAM_PERIOD] = { .type = NLA_U32 },
3811 };
3812
Jeff Johnson1f61b612016-02-12 16:28:33 -08003813 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814
Anurag Chouhan6d760662016-02-20 16:05:43 +05303815 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 hdd_err("Command not allowed in FTM mode");
3817 return -EPERM;
3818 }
3819
3820 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303821 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823
3824 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
3825 hddLog(LOGE,
3826 FL("Periodic Tx Pattern Offload feature is not supported in FW!"));
3827 return -ENOTSUPP;
3828 }
3829
3830 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3831 hddLog(LOGE, FL("Invalid ATTR"));
3832 return -EINVAL;
3833 }
3834
3835 if (!tb[PARAM_CONTROL]) {
3836 hddLog(LOGE, FL("attr control failed"));
3837 return -EINVAL;
3838 }
3839 control = nla_get_u32(tb[PARAM_CONTROL]);
3840 hddLog(LOG1, FL("Control: %d"), control);
3841
3842 if (control == WLAN_START_OFFLOADED_PACKETS)
3843 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
3844 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
3845 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
3846 else {
3847 hddLog(LOGE, FL("Invalid control: %d"), control);
3848 return -EINVAL;
3849 }
3850}
3851
3852/*
3853 * done with short names for the global vendor params
3854 * used by __wlan_hdd_cfg80211_offloaded_packets()
3855 */
3856#undef PARAM_MAX
3857#undef PARAM_REQUEST_ID
3858#undef PARAM_CONTROL
3859#undef PARAM_IP_PACKET
3860#undef PARAM_SRC_MAC_ADDR
3861#undef PARAM_DST_MAC_ADDR
3862#undef PARAM_PERIOD
3863
3864/**
3865 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
3866 * @wiphy: wiphy structure pointer
3867 * @wdev: Wireless device structure pointer
3868 * @data: Pointer to the data received
3869 * @data_len: Length of @data
3870 *
3871 * Return: 0 on success; errno on failure
3872 */
3873static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3874 struct wireless_dev *wdev,
3875 const void *data,
3876 int data_len)
3877{
3878 int ret = 0;
3879
3880 cds_ssr_protect(__func__);
3881 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
3882 wdev, data, data_len);
3883 cds_ssr_unprotect(__func__);
3884
3885 return ret;
3886}
3887#endif
3888
3889/*
3890 * define short names for the global vendor params
3891 * used by __wlan_hdd_cfg80211_monitor_rssi()
3892 */
3893#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
3894#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
3895#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
3896#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
3897#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
3898
3899/**
3900 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
3901 * @wiphy: Pointer to wireless phy
3902 * @wdev: Pointer to wireless device
3903 * @data: Pointer to data
3904 * @data_len: Data length
3905 *
3906 * Return: 0 on success, negative errno on failure
3907 */
3908static int
3909__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
3910 struct wireless_dev *wdev,
3911 const void *data,
3912 int data_len)
3913{
3914 struct net_device *dev = wdev->netdev;
3915 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3916 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3917 struct nlattr *tb[PARAM_MAX + 1];
3918 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303919 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 int ret;
3921 uint32_t control;
3922 static const struct nla_policy policy[PARAM_MAX + 1] = {
3923 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3924 [PARAM_CONTROL] = { .type = NLA_U32 },
3925 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
3926 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
3927 };
3928
Jeff Johnson1f61b612016-02-12 16:28:33 -08003929 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930
3931 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303932 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934
3935 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3936 hddLog(LOGE, FL("Not in Connected state!"));
3937 return -ENOTSUPP;
3938 }
3939
3940 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3941 hddLog(LOGE, FL("Invalid ATTR"));
3942 return -EINVAL;
3943 }
3944
3945 if (!tb[PARAM_REQUEST_ID]) {
3946 hddLog(LOGE, FL("attr request id failed"));
3947 return -EINVAL;
3948 }
3949
3950 if (!tb[PARAM_CONTROL]) {
3951 hddLog(LOGE, FL("attr control failed"));
3952 return -EINVAL;
3953 }
3954
3955 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3956 req.session_id = adapter->sessionId;
3957 control = nla_get_u32(tb[PARAM_CONTROL]);
3958
3959 if (control == QCA_WLAN_RSSI_MONITORING_START) {
3960 req.control = true;
3961 if (!tb[PARAM_MIN_RSSI]) {
3962 hddLog(LOGE, FL("attr min rssi failed"));
3963 return -EINVAL;
3964 }
3965
3966 if (!tb[PARAM_MAX_RSSI]) {
3967 hddLog(LOGE, FL("attr max rssi failed"));
3968 return -EINVAL;
3969 }
3970
3971 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
3972 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
3973
3974 if (!(req.min_rssi < req.max_rssi)) {
3975 hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"),
3976 req.min_rssi, req.max_rssi);
3977 return -EINVAL;
3978 }
3979 hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"),
3980 req.min_rssi, req.max_rssi);
3981
3982 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
3983 req.control = false;
3984 else {
3985 hddLog(LOGE, FL("Invalid control cmd: %d"), control);
3986 return -EINVAL;
3987 }
3988 hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"),
3989 req.request_id, req.session_id, req.control);
3990
3991 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303992 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993 hddLog(LOGE,
3994 FL("sme_set_rssi_monitoring failed(err=%d)"), status);
3995 return -EINVAL;
3996 }
3997
3998 return 0;
3999}
4000
4001/*
4002 * done with short names for the global vendor params
4003 * used by __wlan_hdd_cfg80211_monitor_rssi()
4004 */
4005#undef PARAM_MAX
4006#undef PARAM_CONTROL
4007#undef PARAM_REQUEST_ID
4008#undef PARAM_MAX_RSSI
4009#undef PARAM_MIN_RSSI
4010
4011/**
4012 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4013 * @wiphy: wiphy structure pointer
4014 * @wdev: Wireless device structure pointer
4015 * @data: Pointer to the data received
4016 * @data_len: Length of @data
4017 *
4018 * Return: 0 on success; errno on failure
4019 */
4020static int
4021wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4022 const void *data, int data_len)
4023{
4024 int ret;
4025
4026 cds_ssr_protect(__func__);
4027 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4028 cds_ssr_unprotect(__func__);
4029
4030 return ret;
4031}
4032
4033/**
4034 * hdd_rssi_threshold_breached() - rssi breached NL event
4035 * @hddctx: HDD context
4036 * @data: rssi breached event data
4037 *
4038 * This function reads the rssi breached event %data and fill in the skb with
4039 * NL attributes and send up the NL event.
4040 *
4041 * Return: none
4042 */
4043void hdd_rssi_threshold_breached(void *hddctx,
4044 struct rssi_breach_event *data)
4045{
4046 hdd_context_t *hdd_ctx = hddctx;
4047 struct sk_buff *skb;
4048
4049 ENTER();
4050
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304051 if (wlan_hdd_validate_context(hdd_ctx))
4052 return;
4053 if (!data) {
4054 hddLog(LOGE, FL("data is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 return;
4056 }
4057
4058 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4059 NULL,
4060 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4061 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4062 GFP_KERNEL);
4063
4064 if (!skb) {
4065 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
4066 return;
4067 }
4068
4069 hddLog(LOG1, "Req Id: %u Current rssi: %d",
4070 data->request_id, data->curr_rssi);
4071 hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR,
4072 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4073
4074 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4075 data->request_id) ||
4076 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4077 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4078 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4079 data->curr_rssi)) {
4080 hddLog(LOGE, FL("nla put fail"));
4081 goto fail;
4082 }
4083
4084 cfg80211_vendor_event(skb, GFP_KERNEL);
4085 return;
4086
4087fail:
4088 kfree_skb(skb);
4089 return;
4090}
4091
4092/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
4093 * @wiphy: Pointer to wireless phy
4094 * @wdev: Pointer to wireless device
4095 * @data: Pointer to data
4096 * @data_len: Data length
4097 *
4098 * This function return the preferred frequency list generated by the policy
4099 * manager.
4100 *
4101 * Return: success or failure code
4102 */
4103static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4104 struct wireless_dev
4105 *wdev, const void *data,
4106 int data_len)
4107{
4108 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4109 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304110 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 uint8_t pcl[MAX_NUM_CHAN];
4112 uint32_t pcl_len = 0;
4113 uint32_t freq_list[MAX_NUM_CHAN];
4114 enum cds_con_mode intf_mode;
4115 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4116 struct sk_buff *reply_skb;
4117
Jeff Johnson1f61b612016-02-12 16:28:33 -08004118 ENTER_DEV(wdev->netdev);
4119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 ret = wlan_hdd_validate_context(hdd_ctx);
4121 if (ret)
4122 return -EINVAL;
4123
4124 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4125 data, data_len, NULL)) {
4126 hdd_err("Invalid ATTR");
4127 return -EINVAL;
4128 }
4129
4130 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4131 hdd_err("attr interface type failed");
4132 return -EINVAL;
4133 }
4134
4135 intf_mode = nla_get_u32(tb
4136 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4137
4138 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4139 hdd_err("Invalid interface type");
4140 return -EINVAL;
4141 }
4142
4143 hdd_debug("Userspace requested pref freq list");
4144
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004145 status = cds_get_pcl(intf_mode, pcl, &pcl_len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304146 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 hdd_err("Get pcl failed");
4148 return -EINVAL;
4149 }
4150
4151 /* convert channel number to frequency */
4152 for (i = 0; i < pcl_len; i++) {
4153 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4154 freq_list[i] =
4155 ieee80211_channel_to_frequency(pcl[i],
4156 IEEE80211_BAND_2GHZ);
4157 else
4158 freq_list[i] =
4159 ieee80211_channel_to_frequency(pcl[i],
4160 IEEE80211_BAND_5GHZ);
4161 }
4162
4163 /* send the freq_list back to supplicant */
4164 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4165 sizeof(u32) *
4166 pcl_len +
4167 NLMSG_HDRLEN);
4168
4169 if (!reply_skb) {
4170 hdd_err("Allocate reply_skb failed");
4171 return -EINVAL;
4172 }
4173
4174 if (nla_put_u32(reply_skb,
4175 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4176 intf_mode) ||
4177 nla_put(reply_skb,
4178 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4179 sizeof(uint32_t) * pcl_len,
4180 freq_list)) {
4181 hdd_err("nla put fail");
4182 kfree_skb(reply_skb);
4183 return -EINVAL;
4184 }
4185
4186 return cfg80211_vendor_cmd_reply(reply_skb);
4187}
4188
4189/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4190 * @wiphy: Pointer to wireless phy
4191 * @wdev: Pointer to wireless device
4192 * @data: Pointer to data
4193 * @data_len: Data length
4194 *
4195 * This function return the preferred frequency list generated by the policy
4196 * manager.
4197 *
4198 * Return: success or failure code
4199 */
4200static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4201 struct wireless_dev
4202 *wdev, const void *data,
4203 int data_len)
4204{
4205 int ret = 0;
4206
4207 cds_ssr_protect(__func__);
4208 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
4209 data, data_len);
4210 cds_ssr_unprotect(__func__);
4211
4212 return ret;
4213}
4214
4215/**
4216 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4217 * @wiphy: Pointer to wireless phy
4218 * @wdev: Pointer to wireless device
4219 * @data: Pointer to data
4220 * @data_len: Data length
4221 *
4222 * Return: 0 on success, negative errno on failure
4223 */
4224static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4225 struct wireless_dev *wdev,
4226 const void *data,
4227 int data_len)
4228{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304229 struct net_device *ndev = wdev->netdev;
4230 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4232 int ret = 0;
4233 enum cds_con_mode intf_mode;
4234 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4235 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236
Jeff Johnson1f61b612016-02-12 16:28:33 -08004237 ENTER_DEV(ndev);
4238
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004239 ret = wlan_hdd_validate_context(hdd_ctx);
4240 if (ret)
4241 return ret;
4242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
4244 data, data_len, NULL)) {
4245 hdd_err("Invalid ATTR");
4246 return -EINVAL;
4247 }
4248
4249 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
4250 hdd_err("attr interface type failed");
4251 return -EINVAL;
4252 }
4253
4254 intf_mode = nla_get_u32(tb
4255 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
4256
4257 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4258 hdd_err("Invalid interface type");
4259 return -EINVAL;
4260 }
4261
4262 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
4263 hdd_err("attr probable freq failed");
4264 return -EINVAL;
4265 }
4266
4267 channel_hint = cds_freq_to_chan(nla_get_u32(tb
4268 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
4269
4270 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004271 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 channel_hint, HW_MODE_20_MHZ)) {
4273 hdd_err("Set channel hint failed due to concurrency check");
4274 return -EINVAL;
4275 }
4276
4277 if (hdd_ctx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304278 ret = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304279 if (!QDF_IS_STATUS_SUCCESS(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 hdd_err("clearing event failed");
4281
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304282 ret = cds_current_connections_update(adapter->sessionId,
4283 channel_hint,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05304284 SIR_UPDATE_REASON_SET_OPER_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304285 if (QDF_STATUS_E_FAILURE == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 /* return in the failure case */
4287 hdd_err("ERROR: connections update failed!!");
4288 return -EINVAL;
4289 }
4290
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304291 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292 /*
4293 * Success is the only case for which we expect hw mode
4294 * change to take place, hence we need to wait.
4295 * For any other return value it should be a pass
4296 * through
4297 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304298 ret = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304299 if (!QDF_IS_STATUS_SUCCESS(ret)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304300 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 return -EINVAL;
4302 }
4303
4304 }
4305 }
4306
4307 return 0;
4308}
4309
4310/**
4311 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4312 * @wiphy: Pointer to wireless phy
4313 * @wdev: Pointer to wireless device
4314 * @data: Pointer to data
4315 * @data_len: Data length
4316 *
4317 * Return: 0 on success, negative errno on failure
4318 */
4319static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4320 struct wireless_dev *wdev,
4321 const void *data,
4322 int data_len)
4323{
4324 int ret = 0;
4325
4326 cds_ssr_protect(__func__);
4327 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
4328 data, data_len);
4329 cds_ssr_unprotect(__func__);
4330
4331 return ret;
4332}
4333
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304334static const struct
4335nla_policy
4336qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
4337 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
4338};
4339
4340/**
4341 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
4342 * @wiphy: WIPHY structure pointer
4343 * @wdev: Wireless device structure pointer
4344 * @data: Pointer to the data received
4345 * @data_len: Length of the data received
4346 *
4347 * This function is used to get link properties like nss, rate flags and
4348 * operating frequency for the active connection with the given peer.
4349 *
4350 * Return: 0 on success and errno on failure
4351 */
4352static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4353 struct wireless_dev *wdev,
4354 const void *data,
4355 int data_len)
4356{
4357 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4358 struct net_device *dev = wdev->netdev;
4359 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4360 hdd_station_ctx_t *hdd_sta_ctx;
4361 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05304362 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304363 uint32_t sta_id;
4364 struct sk_buff *reply_skb;
4365 uint32_t rate_flags = 0;
4366 uint8_t nss;
4367 uint8_t final_rate_flags = 0;
4368 uint32_t freq;
4369
Jeff Johnson1f61b612016-02-12 16:28:33 -08004370 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304371
Anurag Chouhan6d760662016-02-20 16:05:43 +05304372 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304373 hdd_err("Command not allowed in FTM mode");
4374 return -EPERM;
4375 }
4376
4377 if (0 != wlan_hdd_validate_context(hdd_ctx))
4378 return -EINVAL;
4379
4380 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
4381 qca_wlan_vendor_attr_policy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304382 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid attribute"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304383 return -EINVAL;
4384 }
4385
4386 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304387 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304388 FL("Attribute peerMac not provided for mode=%d"),
4389 adapter->device_mode);
4390 return -EINVAL;
4391 }
4392
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304393 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05304394 QDF_MAC_ADDR_SIZE);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304395 hddLog(QDF_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304396 FL("peerMac="MAC_ADDRESS_STR" for device_mode:%d"),
4397 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
4398
4399 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
4400 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
4401 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4402 if ((hdd_sta_ctx->conn_info.connState !=
4403 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304404 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304405 peer_mac, QDF_MAC_ADDR_SIZE)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304406 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304407 FL("Not Associated to mac "MAC_ADDRESS_STR),
4408 MAC_ADDR_ARRAY(peer_mac));
4409 return -EINVAL;
4410 }
4411
4412 nss = hdd_sta_ctx->conn_info.nss;
4413 freq = cds_chan_to_freq(
4414 hdd_sta_ctx->conn_info.operationChannel);
4415 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
4416 } else if (adapter->device_mode == WLAN_HDD_P2P_GO ||
4417 adapter->device_mode == WLAN_HDD_SOFTAP) {
4418
4419 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
4420 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05304421 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304422 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304423 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304424 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304425 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304426 break;
4427 }
4428
4429 if (WLAN_MAX_STA_COUNT == sta_id) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304430 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304431 FL("No active peer with mac="MAC_ADDRESS_STR),
4432 MAC_ADDR_ARRAY(peer_mac));
4433 return -EINVAL;
4434 }
4435
4436 nss = adapter->aStaInfo[sta_id].nss;
4437 freq = cds_chan_to_freq(
4438 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
4439 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
4440 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304441 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304442 FL("Not Associated! with mac "MAC_ADDRESS_STR),
4443 MAC_ADDR_ARRAY(peer_mac));
4444 return -EINVAL;
4445 }
4446
4447 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
4448 if (rate_flags & eHAL_TX_RATE_VHT80) {
4449 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004450#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304451 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004452#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304453 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
4454 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004455#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304456 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004457#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304458 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
4459 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4460 } else if (rate_flags &
4461 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
4462 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004463#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304464 if (rate_flags & eHAL_TX_RATE_HT40)
4465 final_rate_flags |=
4466 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004467#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304468 }
4469
4470 if (rate_flags & eHAL_TX_RATE_SGI) {
4471 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
4472 final_rate_flags |= RATE_INFO_FLAGS_MCS;
4473 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
4474 }
4475 }
4476
4477 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4478 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
4479
4480 if (NULL == reply_skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304481 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304482 FL("getLinkProperties: skb alloc failed"));
4483 return -EINVAL;
4484 }
4485
4486 if (nla_put_u8(reply_skb,
4487 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
4488 nss) ||
4489 nla_put_u8(reply_skb,
4490 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
4491 final_rate_flags) ||
4492 nla_put_u32(reply_skb,
4493 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
4494 freq)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304495 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla_put failed"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304496 kfree_skb(reply_skb);
4497 return -EINVAL;
4498 }
4499
4500 return cfg80211_vendor_cmd_reply(reply_skb);
4501}
4502
4503/**
4504 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
4505 * properties.
4506 * @wiphy: WIPHY structure pointer
4507 * @wdev: Wireless device structure pointer
4508 * @data: Pointer to the data received
4509 * @data_len: Length of the data received
4510 *
4511 * This function is used to get link properties like nss, rate flags and
4512 * operating frequency for the active connection with the given peer.
4513 *
4514 * Return: 0 on success and errno on failure
4515 */
4516static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4517 struct wireless_dev *wdev,
4518 const void *data,
4519 int data_len)
4520{
4521 int ret = 0;
4522
4523 cds_ssr_protect(__func__);
4524 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
4525 wdev, data, data_len);
4526 cds_ssr_unprotect(__func__);
4527
4528 return ret;
4529}
4530
Peng Xu278d0122015-09-24 16:34:17 -07004531static const struct
4532nla_policy
4533qca_wlan_vendor_ota_test_policy
4534[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
4535 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
4536};
4537
4538/**
4539 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
4540 * @wiphy: Pointer to wireless phy
4541 * @wdev: Pointer to wireless device
4542 * @data: Pointer to data
4543 * @data_len: Data length
4544 *
4545 * Return: 0 on success, negative errno on failure
4546 */
4547static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4548 struct wireless_dev *wdev,
4549 const void *data,
4550 int data_len)
4551{
4552 struct net_device *dev = wdev->netdev;
4553 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4554 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
4555 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4556 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
4557 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304558 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07004559 uint32_t current_roam_state;
4560
Jeff Johnson1f61b612016-02-12 16:28:33 -08004561 ENTER_DEV(dev);
4562
Anurag Chouhan6d760662016-02-20 16:05:43 +05304563 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07004564 hdd_err("Command not allowed in FTM mode");
4565 return -EPERM;
4566 }
4567
4568 if (0 != wlan_hdd_validate_context(hdd_ctx))
4569 return -EINVAL;
4570
4571 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
4572 data, data_len,
4573 qca_wlan_vendor_ota_test_policy)) {
4574 hdd_err("invalid attr");
4575 return -EINVAL;
4576 }
4577
4578 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
4579 hdd_err("attr ota test failed");
4580 return -EINVAL;
4581 }
4582
4583 ota_enable = nla_get_u8(
4584 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
4585
4586 hdd_info(" OTA test enable = %d", ota_enable);
4587 if (ota_enable != 1) {
4588 hdd_err("Invalid value, only enable test mode is supported!");
4589 return -EINVAL;
4590 }
4591
4592 current_roam_state =
4593 sme_get_current_roam_state(hal, adapter->sessionId);
4594 status = sme_stop_roaming(hal, adapter->sessionId,
4595 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304596 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004597 hdd_err("Enable/Disable roaming failed");
4598 return -EINVAL;
4599 }
4600
4601 status = sme_ps_enable_disable(hal, adapter->sessionId,
4602 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304603 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004604 hdd_err("Enable/Disable power save failed");
4605 /* restore previous roaming setting */
4606 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
4607 current_roam_state == eCSR_ROAMING_STATE_JOINED)
4608 status = sme_start_roaming(hal, adapter->sessionId,
4609 eCsrHddIssued);
4610 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
4611 current_roam_state == eCSR_ROAMING_STATE_IDLE)
4612 status = sme_stop_roaming(hal, adapter->sessionId,
4613 eCsrHddIssued);
4614
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304615 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07004616 hdd_err("Restoring roaming state failed");
4617
4618 return -EINVAL;
4619 }
4620
4621
4622 return 0;
4623}
4624
4625/**
4626 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
4627 * @wiphy: Pointer to wireless phy
4628 * @wdev: Pointer to wireless device
4629 * @data: Pointer to data
4630 * @data_len: Data length
4631 *
4632 * Return: 0 on success, negative errno on failure
4633 */
4634static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4635 struct wireless_dev *wdev,
4636 const void *data,
4637 int data_len)
4638{
4639 int ret = 0;
4640
4641 cds_ssr_protect(__func__);
4642 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
4643 cds_ssr_unprotect(__func__);
4644
4645 return ret;
4646}
4647
Peng Xu4d67c8f2015-10-16 16:02:26 -07004648/**
4649 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4650 * @wiphy: Pointer to wireless phy
4651 * @wdev: Pointer to wireless device
4652 * @data: Pointer to data
4653 * @data_len: Data length
4654 *
4655 * Return: 0 on success, negative errno on failure
4656 */
4657static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4658 struct wireless_dev *wdev,
4659 const void *data,
4660 int data_len)
4661{
4662 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4663 struct net_device *dev = wdev->netdev;
4664 hdd_adapter_t *adapter = NULL;
4665 int ret = 0;
4666 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
4667 uint8_t scale_value;
4668
Jeff Johnson1f61b612016-02-12 16:28:33 -08004669 ENTER_DEV(dev);
4670
Peng Xu4d67c8f2015-10-16 16:02:26 -07004671 ret = wlan_hdd_validate_context(hdd_ctx);
4672 if (ret)
4673 return ret;
4674
4675 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4676
4677 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
4678 data, data_len, NULL)) {
4679 hdd_err("Invalid ATTR");
4680 return -EINVAL;
4681 }
4682
4683 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
4684 hdd_err("attr tx power scale failed");
4685 return -EINVAL;
4686 }
4687
4688 scale_value = nla_get_u8(tb
4689 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
4690
4691 if (scale_value > MAX_TXPOWER_SCALE) {
4692 hdd_err("Invalid tx power scale level");
4693 return -EINVAL;
4694 }
4695
4696 ret = wma_set_tx_power_scale(adapter->sessionId, scale_value);
4697
4698 if (ret != 0) {
4699 hdd_err("Set tx power scale failed");
4700 return -EINVAL;
4701 }
4702
4703 return 0;
4704}
4705
4706/**
4707 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4708 * @wiphy: Pointer to wireless phy
4709 * @wdev: Pointer to wireless device
4710 * @data: Pointer to data
4711 * @data_len: Data length
4712 *
4713 * Return: 0 on success, negative errno on failure
4714 */
4715static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4716 struct wireless_dev *wdev,
4717 const void *data,
4718 int data_len)
4719{
4720 int ret = 0;
4721
4722 cds_ssr_protect(__func__);
4723 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
4724 data, data_len);
4725 cds_ssr_unprotect(__func__);
4726
4727 return ret;
4728}
4729
4730/**
4731 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4732 * @wiphy: Pointer to wireless phy
4733 * @wdev: Pointer to wireless device
4734 * @data: Pointer to data
4735 * @data_len: Data length
4736 *
4737 * Return: 0 on success, negative errno on failure
4738 */
4739static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4740 struct wireless_dev *wdev,
4741 const void *data,
4742 int data_len)
4743{
4744 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4745 struct net_device *dev = wdev->netdev;
4746 hdd_adapter_t *adapter = NULL;
4747 int ret = 0;
4748 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
4749 uint8_t scale_value;
4750
Jeff Johnson1f61b612016-02-12 16:28:33 -08004751 ENTER_DEV(dev);
4752
Peng Xu4d67c8f2015-10-16 16:02:26 -07004753 ret = wlan_hdd_validate_context(hdd_ctx);
4754 if (ret)
4755 return ret;
4756
4757 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4758
4759 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
4760 data, data_len, NULL)) {
4761 hdd_err("Invalid ATTR");
4762 return -EINVAL;
4763 }
4764
4765 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
4766 hdd_err("attr tx power decrease db value failed");
4767 return -EINVAL;
4768 }
4769
4770 scale_value = nla_get_u8(tb
4771 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
4772
4773 ret = wma_set_tx_power_scale_decr_db(adapter->sessionId, scale_value);
4774
4775 if (ret != 0) {
4776 hdd_err("Set tx power decrease db failed");
4777 return -EINVAL;
4778 }
4779
4780 return 0;
4781}
4782
4783/**
4784 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4785 * @wiphy: Pointer to wireless phy
4786 * @wdev: Pointer to wireless device
4787 * @data: Pointer to data
4788 * @data_len: Data length
4789 *
4790 * Return: 0 on success, negative errno on failure
4791 */
4792static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4793 struct wireless_dev *wdev,
4794 const void *data,
4795 int data_len)
4796{
4797 int ret = 0;
4798
4799 cds_ssr_protect(__func__);
4800 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
4801 data, data_len);
4802 cds_ssr_unprotect(__func__);
4803
4804 return ret;
4805}
4806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
4808 {
4809 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4810 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
4811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4812 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4813 .doit = is_driver_dfs_capable
4814 },
4815
4816#ifdef WLAN_FEATURE_NAN
4817 {
4818 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4819 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
4820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4821 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4822 .doit = wlan_hdd_cfg80211_nan_request
4823 },
4824#endif
4825
4826#ifdef WLAN_FEATURE_STATS_EXT
4827 {
4828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4829 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
4830 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4831 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4832 .doit = wlan_hdd_cfg80211_stats_ext_request
4833 },
4834#endif
4835#ifdef FEATURE_WLAN_EXTSCAN
4836 {
4837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
4839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4840 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4841 .doit = wlan_hdd_cfg80211_extscan_start
4842 },
4843 {
4844 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4845 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
4846 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4847 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4848 .doit = wlan_hdd_cfg80211_extscan_stop
4849 },
4850 {
4851 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4852 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
4853 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4854 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
4855 },
4856 {
4857 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4858 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
4859 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4860 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4861 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
4862 },
4863 {
4864 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4865 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
4866 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4867 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4868 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
4869 },
4870 {
4871 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4872 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
4873 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4874 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4875 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
4876 },
4877 {
4878 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4879 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
4880 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4881 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4882 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
4883 },
4884 {
4885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4886 .info.subcmd =
4887 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
4888 .flags =
4889 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4890 WIPHY_VENDOR_CMD_NEED_RUNNING,
4891 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
4892 },
4893 {
4894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4895 .info.subcmd =
4896 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
4897 .flags =
4898 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4899 WIPHY_VENDOR_CMD_NEED_RUNNING,
4900 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
4901 },
4902 {
4903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4904 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
4905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4906 WIPHY_VENDOR_CMD_NEED_NETDEV |
4907 WIPHY_VENDOR_CMD_NEED_RUNNING,
4908 .doit = wlan_hdd_cfg80211_set_epno_list
4909 },
4910#endif /* FEATURE_WLAN_EXTSCAN */
4911
4912#ifdef WLAN_FEATURE_LINK_LAYER_STATS
4913 {
4914 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4915 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
4916 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4917 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4918 .doit = wlan_hdd_cfg80211_ll_stats_clear
4919 },
4920
4921 {
4922 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4923 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
4924 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4925 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4926 .doit = wlan_hdd_cfg80211_ll_stats_set
4927 },
4928
4929 {
4930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4931 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
4932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4933 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4934 .doit = wlan_hdd_cfg80211_ll_stats_get
4935 },
4936#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
4937#ifdef FEATURE_WLAN_TDLS
4938 {
4939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
4941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4942 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4943 .doit = wlan_hdd_cfg80211_exttdls_enable
4944 },
4945 {
4946 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4947 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
4948 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4949 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4950 .doit = wlan_hdd_cfg80211_exttdls_disable
4951 },
4952 {
4953 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4954 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
4955 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4956 .doit = wlan_hdd_cfg80211_exttdls_get_status
4957 },
4958#endif
4959 {
4960 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4961 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
4962 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4963 .doit = wlan_hdd_cfg80211_get_supported_features
4964 },
4965 {
4966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4967 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
4968 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4969 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
4970 },
4971 {
4972 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4973 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
4974 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4975 .doit = cds_cfg80211_get_concurrency_matrix
4976 },
4977 {
4978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
4980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4981 WIPHY_VENDOR_CMD_NEED_NETDEV,
4982 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
4983 },
4984
4985 {
4986 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4987 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
4988 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4989 WIPHY_VENDOR_CMD_NEED_NETDEV |
4990 WIPHY_VENDOR_CMD_NEED_RUNNING,
4991 .doit = wlan_hdd_cfg80211_do_acs
4992 },
4993
4994 {
4995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
4997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4998 WIPHY_VENDOR_CMD_NEED_NETDEV,
4999 .doit = wlan_hdd_cfg80211_get_features
5000 },
5001#ifdef WLAN_FEATURE_ROAM_OFFLOAD
5002 {
5003 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5004 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
5005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5006 WIPHY_VENDOR_CMD_NEED_NETDEV |
5007 WIPHY_VENDOR_CMD_NEED_RUNNING,
5008 .doit = wlan_hdd_cfg80211_keymgmt_set_key
5009 },
5010#endif
5011#ifdef FEATURE_WLAN_EXTSCAN
5012 {
5013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
5015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5016 WIPHY_VENDOR_CMD_NEED_NETDEV |
5017 WIPHY_VENDOR_CMD_NEED_RUNNING,
5018 .doit = wlan_hdd_cfg80211_set_passpoint_list
5019 },
5020 {
5021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5022 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
5023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5024 WIPHY_VENDOR_CMD_NEED_NETDEV |
5025 WIPHY_VENDOR_CMD_NEED_RUNNING,
5026 .doit = wlan_hdd_cfg80211_reset_passpoint_list
5027 },
5028 {
5029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
5031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5032 WIPHY_VENDOR_CMD_NEED_NETDEV |
5033 WIPHY_VENDOR_CMD_NEED_RUNNING,
5034 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
5035 },
5036 {
5037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
5039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5040 WIPHY_VENDOR_CMD_NEED_NETDEV |
5041 WIPHY_VENDOR_CMD_NEED_RUNNING,
5042 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
5043 },
5044#endif /* FEATURE_WLAN_EXTSCAN */
5045 {
5046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
5048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5049 WIPHY_VENDOR_CMD_NEED_NETDEV,
5050 .doit = wlan_hdd_cfg80211_get_wifi_info
5051 },
5052 {
5053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
5055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5056 WIPHY_VENDOR_CMD_NEED_NETDEV |
5057 WIPHY_VENDOR_CMD_NEED_RUNNING,
5058 .doit = wlan_hdd_cfg80211_wifi_configuration_set
5059 },
5060 {
5061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
5063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5064 WIPHY_VENDOR_CMD_NEED_NETDEV,
5065 .doit = wlan_hdd_cfg80211_set_ext_roam_params
5066 },
5067 {
5068 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5069 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
5070 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5071 WIPHY_VENDOR_CMD_NEED_NETDEV,
5072 .doit = wlan_hdd_cfg80211_wifi_logger_start
5073 },
5074 {
5075 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5076 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
5077 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5078 WIPHY_VENDOR_CMD_NEED_NETDEV,
5079 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
5080 },
5081 {
5082 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5083 .info.subcmd =
5084 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
5085 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5086 WIPHY_VENDOR_CMD_NEED_NETDEV |
5087 WIPHY_VENDOR_CMD_NEED_RUNNING,
5088 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
5089 },
5090 {
5091 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5092 .info.subcmd =
5093 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
5094 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5095 WIPHY_VENDOR_CMD_NEED_NETDEV |
5096 WIPHY_VENDOR_CMD_NEED_RUNNING,
5097 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
5098 },
5099#ifdef FEATURE_WLAN_TDLS
5100 {
5101 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5102 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
5103 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5104 WIPHY_VENDOR_CMD_NEED_NETDEV |
5105 WIPHY_VENDOR_CMD_NEED_RUNNING,
5106 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
5107 },
5108#endif
5109#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5110 {
5111 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5112 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
5113 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5114 WIPHY_VENDOR_CMD_NEED_NETDEV |
5115 WIPHY_VENDOR_CMD_NEED_RUNNING,
5116 .doit = wlan_hdd_cfg80211_offloaded_packets
5117 },
5118#endif
5119 {
5120 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5121 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
5122 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5123 WIPHY_VENDOR_CMD_NEED_NETDEV |
5124 WIPHY_VENDOR_CMD_NEED_RUNNING,
5125 .doit = wlan_hdd_cfg80211_monitor_rssi
5126 },
5127 {
5128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
5130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5131 WIPHY_VENDOR_CMD_NEED_NETDEV |
5132 WIPHY_VENDOR_CMD_NEED_RUNNING,
5133 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
5134 },
5135#ifdef WLAN_FEATURE_MEMDUMP
5136 {
5137 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5138 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
5139 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5140 WIPHY_VENDOR_CMD_NEED_NETDEV |
5141 WIPHY_VENDOR_CMD_NEED_RUNNING,
5142 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
5143 },
5144#endif /* WLAN_FEATURE_MEMDUMP */
5145 {
5146 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5147 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
5148 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5149 WIPHY_VENDOR_CMD_NEED_NETDEV |
5150 WIPHY_VENDOR_CMD_NEED_RUNNING,
5151 .doit = wlan_hdd_cfg80211_vendor_scan
5152 },
5153
5154 /* OCB commands */
5155 {
5156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5157 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
5158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5159 WIPHY_VENDOR_CMD_NEED_NETDEV |
5160 WIPHY_VENDOR_CMD_NEED_RUNNING,
5161 .doit = wlan_hdd_cfg80211_ocb_set_config
5162 },
5163 {
5164 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5165 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
5166 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5167 WIPHY_VENDOR_CMD_NEED_NETDEV |
5168 WIPHY_VENDOR_CMD_NEED_RUNNING,
5169 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
5170 },
5171 {
5172 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5173 .info.subcmd =
5174 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
5175 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5176 WIPHY_VENDOR_CMD_NEED_NETDEV |
5177 WIPHY_VENDOR_CMD_NEED_RUNNING,
5178 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
5179 },
5180 {
5181 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5182 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
5183 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5184 WIPHY_VENDOR_CMD_NEED_NETDEV |
5185 WIPHY_VENDOR_CMD_NEED_RUNNING,
5186 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
5187 },
5188 {
5189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5190 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
5191 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5192 WIPHY_VENDOR_CMD_NEED_NETDEV |
5193 WIPHY_VENDOR_CMD_NEED_RUNNING,
5194 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
5195 },
5196 {
5197 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5198 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
5199 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5200 WIPHY_VENDOR_CMD_NEED_NETDEV |
5201 WIPHY_VENDOR_CMD_NEED_RUNNING,
5202 .doit = wlan_hdd_cfg80211_dcc_get_stats
5203 },
5204 {
5205 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5206 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
5207 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5208 WIPHY_VENDOR_CMD_NEED_NETDEV |
5209 WIPHY_VENDOR_CMD_NEED_RUNNING,
5210 .doit = wlan_hdd_cfg80211_dcc_clear_stats
5211 },
5212 {
5213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5214 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
5215 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5216 WIPHY_VENDOR_CMD_NEED_NETDEV |
5217 WIPHY_VENDOR_CMD_NEED_RUNNING,
5218 .doit = wlan_hdd_cfg80211_dcc_update_ndl
5219 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305220 {
5221 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5222 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
5223 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5224 WIPHY_VENDOR_CMD_NEED_NETDEV |
5225 WIPHY_VENDOR_CMD_NEED_RUNNING,
5226 .doit = wlan_hdd_cfg80211_get_link_properties
5227 },
Peng Xu278d0122015-09-24 16:34:17 -07005228 {
5229 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
5230 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5231 WIPHY_VENDOR_CMD_NEED_NETDEV |
5232 WIPHY_VENDOR_CMD_NEED_RUNNING,
5233 .doit = wlan_hdd_cfg80211_set_ota_test
5234 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08005235#ifdef FEATURE_LFR_SUBNET_DETECTION
5236 {
5237 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5238 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
5239 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5240 WIPHY_VENDOR_CMD_NEED_NETDEV |
5241 WIPHY_VENDOR_CMD_NEED_RUNNING,
5242 .doit = wlan_hdd_cfg80211_set_gateway_params
5243 },
5244#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07005245 {
5246 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
5247 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5248 WIPHY_VENDOR_CMD_NEED_NETDEV |
5249 WIPHY_VENDOR_CMD_NEED_RUNNING,
5250 .doit = wlan_hdd_cfg80211_txpower_scale
5251 },
5252 {
5253 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5254 .info.subcmd =
5255 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
5256 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5257 WIPHY_VENDOR_CMD_NEED_NETDEV |
5258 WIPHY_VENDOR_CMD_NEED_RUNNING,
5259 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
5260 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005261};
5262
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005263/**
5264 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
5265 * @priv_size: Size of the hdd context.
5266 *
5267 * Allocate wiphy context and hdd context.
5268 *
5269 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005271hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272{
5273 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005274 hdd_context_t *hdd_ctx;
5275
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005276 ENTER();
5277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005278 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
5279
5280 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005281 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005282 return NULL;
5283 }
5284
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005285 hdd_ctx = wiphy_priv(wiphy);
5286
5287 hdd_ctx->wiphy = wiphy;
5288
5289 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005290}
5291
5292/*
5293 * FUNCTION: wlan_hdd_cfg80211_update_band
5294 * This function is called from the supplicant through a
5295 * private ioctl to change the band value
5296 */
5297int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
5298{
5299 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07005300 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301
5302 ENTER();
5303
5304 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5305
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005306 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005308
5309 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5310 struct ieee80211_supported_band *band = wiphy->bands[i];
5311
5312 channelEnabledState =
5313 cds_get_channel_state(band->channels[j].
5314 hw_value);
5315
5316 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
5317 /* 5G only */
5318#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5319 /* Enable Social channels for P2P */
5320 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5321 (band->channels[j].center_freq)
5322 && CHANNEL_STATE_ENABLE ==
5323 channelEnabledState)
5324 band->channels[j].flags &=
5325 ~IEEE80211_CHAN_DISABLED;
5326 else
5327#endif
5328 band->channels[j].flags |=
5329 IEEE80211_CHAN_DISABLED;
5330 continue;
5331 } else if (IEEE80211_BAND_5GHZ == i &&
5332 eCSR_BAND_24 == eBand) {
5333 /* 2G only */
5334 band->channels[j].flags |=
5335 IEEE80211_CHAN_DISABLED;
5336 continue;
5337 }
5338
5339 if (CHANNEL_STATE_DISABLE == channelEnabledState ||
5340 CHANNEL_STATE_INVALID == channelEnabledState) {
5341 band->channels[j].flags |=
5342 IEEE80211_CHAN_DISABLED;
5343 } else if (CHANNEL_STATE_DFS == channelEnabledState) {
5344 band->channels[j].flags &=
5345 ~IEEE80211_CHAN_DISABLED;
5346 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
5347 } else {
5348 band->channels[j].flags &=
5349 ~(IEEE80211_CHAN_DISABLED |
5350 IEEE80211_CHAN_RADAR);
5351 }
5352 }
5353 }
5354 return 0;
5355}
5356
5357/*
5358 * FUNCTION: wlan_hdd_cfg80211_init
5359 * This function is called by hdd_wlan_startup()
5360 * during initialization.
5361 * This function is used to initialize and register wiphy structure.
5362 */
5363int wlan_hdd_cfg80211_init(struct device *dev,
5364 struct wiphy *wiphy, struct hdd_config *pCfg)
5365{
5366 int i, j;
5367 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5368
5369 ENTER();
5370
5371 /* Now bind the underlying wlan device with wiphy */
5372 set_wiphy_dev(wiphy, dev);
5373
5374 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
5375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
5377 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005378 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379#else
5380 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005381 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382#endif
5383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005384 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
5385 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
5386 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
5387#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
5388 | WIPHY_FLAG_4ADDR_STATION
5389#endif
5390 | WIPHY_FLAG_OFFCHAN_TX;
5391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5393 wiphy->wowlan = &wowlan_support_cfg80211_init;
5394#else
5395 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
5396 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
5397 wiphy->wowlan.pattern_min_len = 1;
5398 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
5399#endif
5400
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07005401 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402#ifdef FEATURE_WLAN_ESE
5403 || pCfg->isEseIniFeatureEnabled
5404#endif
5405 ) {
5406 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
5407 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408#ifdef FEATURE_WLAN_TDLS
5409 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
5410 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
5411#endif
5412
5413 wiphy->features |= NL80211_FEATURE_HT_IBSS;
5414
5415#ifdef FEATURE_WLAN_SCAN_PNO
5416 if (pCfg->configPNOScanSupport) {
5417 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5418 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
5419 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
5420 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
5421 }
5422#endif /*FEATURE_WLAN_SCAN_PNO */
5423
5424#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05305425 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426#endif
5427
5428 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
5429 driver can still register regulatory callback and
5430 it will get regulatory settings in wiphy->band[], but
5431 driver need to determine what to do with both
5432 regulatory settings */
5433
5434 wiphy->reg_notifier = hdd_reg_notifier;
5435
5436#if defined QCA_WIFI_FTM
5437}
5438#endif
5439
5440 wiphy->max_scan_ssids = MAX_SCAN_SSID;
5441
5442 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
5443
5444 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
5445
5446 /* Supports STATION & AD-HOC modes right now */
5447 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
5448 | BIT(NL80211_IFTYPE_ADHOC)
5449 | BIT(NL80211_IFTYPE_P2P_CLIENT)
5450 | BIT(NL80211_IFTYPE_P2P_GO)
5451 | BIT(NL80211_IFTYPE_AP);
5452
5453 if (pCfg->advertiseConcurrentOperation) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 if (pCfg->enableMCC) {
5455 int i;
5456 for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination);
5457 i++) {
5458 if (!pCfg->allowMCCGODiffBI)
5459 wlan_hdd_iface_combination[i].
5460 beacon_int_infra_match = true;
5461 }
5462 }
5463 wiphy->n_iface_combinations =
5464 ARRAY_SIZE(wlan_hdd_iface_combination);
5465 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466 }
5467
5468 /* Before registering we need to update the ht capabilitied based
5469 * on ini values*/
5470 if (!pCfg->ShortGI20MhzEnable) {
5471 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5472 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5473 wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &=
5474 ~IEEE80211_HT_CAP_SGI_20;
5475 }
5476
5477 if (!pCfg->ShortGI40MhzEnable) {
5478 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
5479 }
5480
5481 if (!pCfg->nChannelBondingMode5GHz) {
5482 wlan_hdd_band_5_ghz.ht_cap.cap &=
5483 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5484 }
5485
5486 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
5487 if (true == hdd_is_5g_supported(pHddCtx)) {
5488 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
5489 }
5490
5491 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5492
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005493 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005494 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005495
5496 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5497 struct ieee80211_supported_band *band = wiphy->bands[i];
5498
5499 if (IEEE80211_BAND_2GHZ == i &&
5500 eCSR_BAND_5G == pCfg->nBandCapability) {
5501 /* 5G only */
5502#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5503 /* Enable social channels for P2P */
5504 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5505 (band->channels[j].center_freq))
5506 band->channels[j].flags &=
5507 ~IEEE80211_CHAN_DISABLED;
5508 else
5509#endif
5510 band->channels[j].flags |=
5511 IEEE80211_CHAN_DISABLED;
5512 continue;
5513 } else if (IEEE80211_BAND_5GHZ == i &&
5514 eCSR_BAND_24 == pCfg->nBandCapability) {
5515 /* 2G only */
5516 band->channels[j].flags |=
5517 IEEE80211_CHAN_DISABLED;
5518 continue;
5519 }
5520 }
5521 }
5522 /*Initialise the supported cipher suite details */
5523 wiphy->cipher_suites = hdd_cipher_suites;
5524 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
5525
5526 /*signal strength in mBm (100*dBm) */
5527 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
5528 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
5529
Anurag Chouhan6d760662016-02-20 16:05:43 +05305530 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 wiphy->n_vendor_commands =
5532 ARRAY_SIZE(hdd_wiphy_vendor_commands);
5533 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
5534
5535 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
5536 wiphy->n_vendor_events =
5537 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
5538 }
5539
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 if (pCfg->enableDFSMasterCap) {
5541 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
5542 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543
5544 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
5545
5546#ifdef QCA_HT_2040_COEX
5547 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
5548#endif
5549
Abhishek Singh1bdb1572015-10-16 16:24:19 +05305550 hdd_add_channel_switch_support(&wiphy->flags);
5551
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552 EXIT();
5553 return 0;
5554}
5555
5556/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305557 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 * initialization. In wlan_hdd_cfg80211_init, only the
5559 * default values will be initialized. The final initialization
5560 * of all required members can be done here.
5561 */
5562void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
5563{
5564 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
5565}
5566
5567/* In this function we are registering wiphy. */
5568int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
5569{
5570 ENTER();
5571 /* Register our wiphy dev with cfg80211 */
5572 if (0 > wiphy_register(wiphy)) {
5573 /* print error */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305574 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: wiphy register failed",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005575 __func__);
5576 return -EIO;
5577 }
5578
5579 EXIT();
5580 return 0;
5581}
5582
5583/*
5584 HDD function to update wiphy capability based on target offload status.
5585
5586 wlan_hdd_cfg80211_init() does initialization of all wiphy related
5587 capability even before downloading firmware to the target. In discrete
5588 case, host will get know certain offload capability (say sched_scan
5589 caps) only after downloading firmware to the target and target boots up.
5590 This function is used to override setting done in wlan_hdd_cfg80211_init()
5591 based on target capability.
5592 */
5593void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
5594{
5595#ifdef FEATURE_WLAN_SCAN_PNO
5596 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5597 struct hdd_config *pCfg = pHddCtx->config;
5598
5599 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
5600 * control comes here. Here just we need to clear it if firmware doesn't
5601 * have PNO support. */
5602 if (!pCfg->PnoOffload) {
5603 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5604 wiphy->max_sched_scan_ssids = 0;
5605 wiphy->max_match_sets = 0;
5606 wiphy->max_sched_scan_ie_len = 0;
5607 }
5608#endif
5609}
5610
5611/* This function registers for all frame which supplicant is interested in */
5612void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
5613{
5614 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5615 /* Register for all P2P action, public action etc frames */
5616 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5617
5618 ENTER();
5619
Abhishek Singh7996eb72015-12-30 17:24:02 +05305620 /* Register frame indication call back */
5621 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
5622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005623 /* Right now we are registering these frame when driver is getting
5624 initialized. Once we will move to 2.6.37 kernel, in which we have
5625 frame register ops, we will move this code as a part of that */
5626 /* GAS Initial Request */
5627 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5628 (uint8_t *) GAS_INITIAL_REQ,
5629 GAS_INITIAL_REQ_SIZE);
5630
5631 /* GAS Initial Response */
5632 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5633 (uint8_t *) GAS_INITIAL_RSP,
5634 GAS_INITIAL_RSP_SIZE);
5635
5636 /* GAS Comeback Request */
5637 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5638 (uint8_t *) GAS_COMEBACK_REQ,
5639 GAS_COMEBACK_REQ_SIZE);
5640
5641 /* GAS Comeback Response */
5642 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5643 (uint8_t *) GAS_COMEBACK_RSP,
5644 GAS_COMEBACK_RSP_SIZE);
5645
5646 /* P2P Public Action */
5647 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5648 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5649 P2P_PUBLIC_ACTION_FRAME_SIZE);
5650
5651 /* P2P Action */
5652 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5653 (uint8_t *) P2P_ACTION_FRAME,
5654 P2P_ACTION_FRAME_SIZE);
5655
5656 /* WNM BSS Transition Request frame */
5657 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5658 (uint8_t *) WNM_BSS_ACTION_FRAME,
5659 WNM_BSS_ACTION_FRAME_SIZE);
5660
5661 /* WNM-Notification */
5662 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
5663 (uint8_t *) WNM_NOTIFICATION_FRAME,
5664 WNM_NOTIFICATION_FRAME_SIZE);
5665}
5666
5667void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
5668{
5669 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5670 /* Register for all P2P action, public action etc frames */
5671 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5672
5673 ENTER();
5674
5675 /* Right now we are registering these frame when driver is getting
5676 initialized. Once we will move to 2.6.37 kernel, in which we have
5677 frame register ops, we will move this code as a part of that */
5678 /* GAS Initial Request */
5679
5680 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5681 (uint8_t *) GAS_INITIAL_REQ,
5682 GAS_INITIAL_REQ_SIZE);
5683
5684 /* GAS Initial Response */
5685 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5686 (uint8_t *) GAS_INITIAL_RSP,
5687 GAS_INITIAL_RSP_SIZE);
5688
5689 /* GAS Comeback Request */
5690 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5691 (uint8_t *) GAS_COMEBACK_REQ,
5692 GAS_COMEBACK_REQ_SIZE);
5693
5694 /* GAS Comeback Response */
5695 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5696 (uint8_t *) GAS_COMEBACK_RSP,
5697 GAS_COMEBACK_RSP_SIZE);
5698
5699 /* P2P Public Action */
5700 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5701 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5702 P2P_PUBLIC_ACTION_FRAME_SIZE);
5703
5704 /* P2P Action */
5705 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5706 (uint8_t *) P2P_ACTION_FRAME,
5707 P2P_ACTION_FRAME_SIZE);
5708
5709 /* WNM-Notification */
5710 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
5711 (uint8_t *) WNM_NOTIFICATION_FRAME,
5712 WNM_NOTIFICATION_FRAME_SIZE);
5713}
5714
5715#ifdef FEATURE_WLAN_WAPI
5716void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
5717 const uint8_t *mac_addr, const uint8_t *key,
5718 int key_Len)
5719{
5720 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5721 tCsrRoamSetKey setKey;
5722 bool isConnected = true;
5723 int status = 0;
5724 uint32_t roamId = 0xFF;
5725 uint8_t *pKeyPtr = NULL;
5726 int n = 0;
5727
5728 hddLog(LOG1, "Device_mode %s(%d)",
5729 hdd_device_mode_to_string(pAdapter->device_mode),
5730 pAdapter->device_mode);
5731
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305732 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 setKey.keyId = key_index; /* Store Key ID */
5734 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
5735 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
5736 setKey.paeRole = 0; /* the PAE role */
5737 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05305738 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005739 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305740 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741 }
5742 setKey.keyLength = key_Len;
5743 pKeyPtr = setKey.Key;
5744 memcpy(pKeyPtr, key, key_Len);
5745
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305746 hddLog(QDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005747 __func__, key_Len);
5748 for (n = 0; n < key_Len; n++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305749 hddLog(QDF_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750 __func__, n, setKey.Key[n]);
5751
5752 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
5753 if (isConnected) {
5754 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
5755 pAdapter->sessionId, &setKey, &roamId);
5756 }
5757 if (status != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305758 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 "[%4d] sme_roam_set_key returned ERROR status= %d",
5760 __LINE__, status);
5761 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
5762 }
5763}
5764#endif /* FEATURE_WLAN_WAPI */
5765
5766uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
5767 uint8_t eid)
5768{
5769 int left = length;
5770 uint8_t *ptr = (uint8_t *)ies_ptr;
5771 uint8_t elem_id, elem_len;
5772
5773 while (left >= 2) {
5774 elem_id = ptr[0];
5775 elem_len = ptr[1];
5776 left -= 2;
5777 if (elem_len > left) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305778 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 FL("Invalid IEs eid = %d elem_len=%d left=%d"),
5780 eid, elem_len, left);
5781 return NULL;
5782 }
5783 if (elem_id == eid) {
5784 return ptr;
5785 }
5786
5787 left -= elem_len;
5788 ptr += (elem_len + 2);
5789 }
5790 return NULL;
5791}
5792
5793/*
5794 * FUNCTION: wlan_hdd_validate_operation_channel
5795 * called by wlan_hdd_cfg80211_start_bss() and
5796 * wlan_hdd_set_channel()
5797 * This function validates whether given channel is part of valid
5798 * channel list.
5799 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305800QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801 int channel)
5802{
5803
5804 uint32_t num_ch = 0;
5805 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5806 u32 indx = 0;
5807 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5808 uint8_t fValidChannel = false, count = 0;
5809 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
5810
5811 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5812
5813 if (hdd_pConfig_ini->sapAllowAllChannel) {
5814 /* Validate the channel */
5815 for (count = RF_CHAN_1; count <= RF_CHAN_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005816 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005817 fValidChannel = true;
5818 break;
5819 }
5820 }
5821 if (fValidChannel != true) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305822 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005823 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305824 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825 }
5826 } else {
5827 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5828 valid_ch, &num_ch)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305829 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 "%s: failed to get valid channel list",
5831 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305832 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 }
5834 for (indx = 0; indx < num_ch; indx++) {
5835 if (channel == valid_ch[indx]) {
5836 break;
5837 }
5838 }
5839
5840 if (indx >= num_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305841 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005842 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305843 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 }
5845 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305846 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005847
5848}
5849
5850#ifdef DHCP_SERVER_OFFLOAD
5851static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
5852{
5853 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
5854 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
5855 uint8_t numEntries = 0;
5856 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
5857 uint8_t num;
5858 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305859 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005860 if (NULL == pDhcpSrvInfo) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305861 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
5863 return;
5864 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305865 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
5867 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
5868 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
5869 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
5870 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
5871 if (numEntries != IPADDR_NUM_ENTRIES) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305872 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005873 "%s: incorrect IP address (%s) assigned for DHCP server!",
5874 __func__, pHddCtx->config->dhcpServerIP);
5875 goto end;
5876 }
5877 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305878 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879 "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
5880 __func__, pHddCtx->config->dhcpServerIP);
5881 goto end;
5882 }
5883 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305884 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 "%s: invalid IP address (%s)! The last field must be less than 100!",
5886 __func__, pHddCtx->config->dhcpServerIP);
5887 goto end;
5888 }
5889 for (num = 0; num < numEntries; num++) {
5890 temp = srv_ip[num];
5891 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
5892 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305893 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305895 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005896 "%s: sme_setDHCPSrvOffload fail!", __func__);
5897 goto end;
5898 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305899 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900 "%s: enable DHCP Server offload successfully!", __func__);
5901end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305902 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005903 return;
5904}
5905#endif /* DHCP_SERVER_OFFLOAD */
5906
5907static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
5908 struct net_device *dev,
5909 struct bss_parameters *params)
5910{
5911 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5912 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5913 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305914 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915
5916 ENTER();
5917
Anurag Chouhan6d760662016-02-20 16:05:43 +05305918 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5920 return -EINVAL;
5921 }
5922
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305923 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
5925 pAdapter->sessionId, params->ap_isolate));
5926 hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"),
5927 hdd_device_mode_to_string(pAdapter->device_mode),
5928 pAdapter->device_mode, params->ap_isolate);
5929
5930 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5931 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305932 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005933 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005934
5935 if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP ||
5936 pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
5937 return -EOPNOTSUPP;
5938 }
5939
5940 /* ap_isolate == -1 means that in change bss, upper layer doesn't
5941 * want to update this parameter */
5942 if (-1 != params->ap_isolate) {
5943 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
5944 !!params->ap_isolate;
5945
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305946 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005947 pAdapter->sessionId,
5948 pAdapter->sessionCtx.
5949 ap.
5950 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305951 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952 ret = -EINVAL;
5953 }
5954 }
5955
5956 EXIT();
5957 return ret;
5958}
5959
Krunal Soni8c37e322016-02-03 16:08:37 -08005960/**
5961 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
5962 * @ndev: pointer to net device provided by supplicant
5963 * @type: type of the interface, upper layer wanted to change
5964 *
5965 * Upper layer provides the new interface mode that needs to be changed
5966 * for given net device
5967 *
5968 * Return: success or failure in terms of integer value
5969 */
5970static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971 enum nl80211_iftype type)
5972{
Krunal Soni8c37e322016-02-03 16:08:37 -08005973 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5974 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
5975 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976 hdd_wext_state_t *wext;
5977 struct wireless_dev *wdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305978 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005979
5980 ENTER();
5981
Krunal Soni8c37e322016-02-03 16:08:37 -08005982 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005983 hddLog(LOG1, FL("ACS is in progress, don't change iface!"));
5984 return 0;
5985 }
5986
5987 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08005988 hdd_stop_adapter(hdd_ctx, adapter, true);
5989 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005990 wdev->iftype = type;
5991 /*Check for sub-string p2p to confirm its a p2p interface */
5992 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08005993 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 (type == NL80211_IFTYPE_STATION) ?
5995 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
Krunal Soni8c37e322016-02-03 16:08:37 -08005996 } else if (type == NL80211_IFTYPE_ADHOC) {
5997 adapter->device_mode = WLAN_HDD_IBSS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005998 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08005999 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006000 (type == NL80211_IFTYPE_STATION) ?
6001 WLAN_HDD_INFRA_STATION : WLAN_HDD_P2P_CLIENT;
6002 }
Krunal Soni8c37e322016-02-03 16:08:37 -08006003 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
6004 hdd_set_station_ops(adapter->dev);
6005 status = hdd_init_station_mode(adapter);
6006 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
6007 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006008 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08006009 adapter->scan_info.scanAddIE.length;
6010 if (type == NL80211_IFTYPE_ADHOC) {
6011 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
6012 wext->roamProfile.phyMode =
6013 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
6014 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 EXIT();
6016 return status;
6017}
6018
6019static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6020 struct net_device *dev,
6021 struct bss_parameters *params)
6022{
6023 int ret;
6024
6025 cds_ssr_protect(__func__);
6026 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
6027 cds_ssr_unprotect(__func__);
6028
6029 return ret;
6030}
6031
6032/* FUNCTION: wlan_hdd_change_country_code_cd
6033 * to wait for contry code completion
6034 */
6035void *wlan_hdd_change_country_code_cb(void *pAdapter)
6036{
6037 hdd_adapter_t *call_back_pAdapter = pAdapter;
6038 complete(&call_back_pAdapter->change_country_code);
6039 return NULL;
6040}
6041
Rajeev Kumar98edb772016-01-19 12:42:19 -08006042/**
6043 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6044 * @wiphy: Pointer to the wiphy structure
6045 * @ndev: Pointer to the net device
6046 * @type: Interface type
6047 * @flags: Flags for change interface
6048 * @params: Pointer to change interface parameters
6049 *
6050 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 */
6052static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6053 struct net_device *ndev,
6054 enum nl80211_iftype type,
6055 u32 *flags,
6056 struct vif_params *params)
6057{
6058 struct wireless_dev *wdev;
6059 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6060 hdd_context_t *pHddCtx;
6061 tCsrRoamProfile *pRoamProfile = NULL;
6062 eCsrRoamBssType LastBSSType;
6063 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306064 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006065 int status;
6066
6067 ENTER();
6068
Anurag Chouhan6d760662016-02-20 16:05:43 +05306069 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006070 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6071 return -EINVAL;
6072 }
6073
6074 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6075 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306076 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006077 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006078
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306079 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006080 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
6081 pAdapter->sessionId, type));
6082
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306083 hddLog(QDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006084 pAdapter->device_mode, type);
6085
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006086 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006087 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
6088 0, HW_MODE_20_MHZ)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306089 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006090 FL("This concurrency combination is not allowed"));
6091 return -EINVAL;
6092 }
6093
6094 pConfig = pHddCtx->config;
6095 wdev = ndev->ieee80211_ptr;
6096
6097 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006098 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006099
6100 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
6101
6102 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6103 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
Krunal Soni2c68f232015-10-26 20:52:51 -07006104 (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE) ||
6105 (pAdapter->device_mode == WLAN_HDD_IBSS)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006106 hdd_wext_state_t *pWextState =
6107 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6108
6109 pRoamProfile = &pWextState->roamProfile;
6110 LastBSSType = pRoamProfile->BSSType;
6111
6112 switch (type) {
6113 case NL80211_IFTYPE_STATION:
6114 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08006115 case NL80211_IFTYPE_ADHOC:
6116 if (type == NL80211_IFTYPE_ADHOC) {
6117 wlan_hdd_tdls_exit(pAdapter);
6118 hdd_deregister_tx_flow_control(pAdapter);
6119 hddLog(LOG1,
6120 FL("Setting interface Type to ADHOC"));
6121 }
6122 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
6123 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306124 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006125 return -EINVAL;
6126
Krunal Soni8c37e322016-02-03 16:08:37 -08006127 /*
6128 * for ibss interface type flow control is not required
6129 * so don't register tx flow control
6130 */
6131 if (type != NL80211_IFTYPE_ADHOC)
6132 hdd_register_tx_flow_control(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006133 hdd_tx_resume_timer_expired_handler,
6134 hdd_tx_resume_cb);
6135
6136 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006137 case NL80211_IFTYPE_AP:
6138 case NL80211_IFTYPE_P2P_GO:
6139 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306140 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006141 FL("Setting interface Type to %s"),
6142 (type ==
6143 NL80211_IFTYPE_AP) ? "SoftAP" :
6144 "P2pGo");
6145
6146 /* Cancel any remain on channel for GO mode */
6147 if (NL80211_IFTYPE_P2P_GO == type) {
6148 wlan_hdd_cancel_existing_remain_on_channel
6149 (pAdapter);
6150 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151 hdd_stop_adapter(pHddCtx, pAdapter, true);
6152
6153 /* De-init the adapter */
6154 hdd_deinit_adapter(pHddCtx, pAdapter, true);
6155 memset(&pAdapter->sessionCtx, 0,
6156 sizeof(pAdapter->sessionCtx));
6157 pAdapter->device_mode =
6158 (type ==
6159 NL80211_IFTYPE_AP) ? WLAN_HDD_SOFTAP :
6160 WLAN_HDD_P2P_GO;
6161
6162 /*
6163 * Fw will take care incase of concurrency
6164 */
6165
6166 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode)
6167 && (pConfig->apRandomBssidEnabled)) {
6168 /* To meet Android requirements create a randomized
6169 MAC address of the form 02:1A:11:Fx:xx:xx */
6170 get_random_bytes(&ndev->dev_addr[3], 3);
6171 ndev->dev_addr[0] = 0x02;
6172 ndev->dev_addr[1] = 0x1A;
6173 ndev->dev_addr[2] = 0x11;
6174 ndev->dev_addr[3] |= 0xF0;
6175 memcpy(pAdapter->macAddressCurrent.
6176 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306177 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006178 pr_info("wlan: Generated HotSpot BSSID "
6179 MAC_ADDRESS_STR "\n",
6180 MAC_ADDR_ARRAY(ndev->dev_addr));
6181 }
6182
6183 hdd_set_ap_ops(pAdapter->dev);
6184
6185 vstatus = hdd_init_ap_mode(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306186 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006187 hddLog(LOGP,
6188 FL
6189 ("Error initializing the ap mode"));
6190 return -EINVAL;
6191 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006192
6193 hdd_register_tx_flow_control(pAdapter,
6194 hdd_softap_tx_resume_timer_expired_handler,
6195 hdd_softap_tx_resume_cb);
6196
6197 /* Interface type changed update in wiphy structure */
6198 if (wdev) {
6199 wdev->iftype = type;
6200 } else {
6201 hddLog(LOGE,
6202 FL("Wireless dev is NULL"));
6203 return -EINVAL;
6204 }
6205 goto done;
6206 }
6207
6208 default:
6209 hddLog(LOGE, FL("Unsupported interface type (%d)"),
6210 type);
6211 return -EOPNOTSUPP;
6212 }
6213 } else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6214 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6215 switch (type) {
6216 case NL80211_IFTYPE_STATION:
6217 case NL80211_IFTYPE_P2P_CLIENT:
6218 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08006219 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
6220 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306221 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006222 return status;
6223
6224 if ((NL80211_IFTYPE_P2P_CLIENT == type) ||
6225 (NL80211_IFTYPE_STATION == type)) {
6226
6227 hdd_register_tx_flow_control(pAdapter,
6228 hdd_tx_resume_timer_expired_handler,
6229 hdd_tx_resume_cb);
6230 }
6231 goto done;
6232
6233 case NL80211_IFTYPE_AP:
6234 case NL80211_IFTYPE_P2P_GO:
6235 wdev->iftype = type;
6236 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
6237 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
6238
6239 hdd_register_tx_flow_control(pAdapter,
6240 hdd_softap_tx_resume_timer_expired_handler,
6241 hdd_softap_tx_resume_cb);
6242 goto done;
6243
6244 default:
6245 hddLog(LOGE, FL("Unsupported interface type(%d)"),
6246 type);
6247 return -EOPNOTSUPP;
6248 }
6249 } else {
6250 hddLog(LOGE, FL("Unsupported device mode(%d)"),
6251 pAdapter->device_mode);
6252 return -EOPNOTSUPP;
6253 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254done:
6255 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006256 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006257
6258#ifdef WLAN_FEATURE_LPSS
6259 wlan_hdd_send_all_scan_intf_info(pHddCtx);
6260#endif
6261
6262 EXIT();
6263 return 0;
6264}
6265
Rajeev Kumar98edb772016-01-19 12:42:19 -08006266/**
6267 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6268 * @wiphy: Pointer to the wiphy structure
6269 * @ndev: Pointer to the net device
6270 * @type: Interface type
6271 * @flags: Flags for change interface
6272 * @params: Pointer to change interface parameters
6273 *
6274 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275 */
6276static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6277 struct net_device *ndev,
6278 enum nl80211_iftype type,
6279 u32 *flags,
6280 struct vif_params *params)
6281{
6282 int ret;
6283
6284 cds_ssr_protect(__func__);
6285 ret =
6286 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
6287 cds_ssr_unprotect(__func__);
6288
6289 return ret;
6290}
6291
6292#ifdef FEATURE_WLAN_TDLS
6293static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
6294 int index, uint8_t match)
6295{
6296 int i;
6297 for (i = 0; i < index; i++) {
6298 if (arr[i] == match)
6299 return true;
6300 }
6301 return false;
6302}
6303#endif
6304
6305/**
6306 * __wlan_hdd_change_station() - change station
6307 * @wiphy: Pointer to the wiphy structure
6308 * @dev: Pointer to the net device.
6309 * @mac: bssid
6310 * @params: Pointer to station parameters
6311 *
6312 * Return: 0 for success, error number on failure.
6313 */
6314#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6315static int __wlan_hdd_change_station(struct wiphy *wiphy,
6316 struct net_device *dev,
6317 const uint8_t *mac,
6318 struct station_parameters *params)
6319#else
6320static int __wlan_hdd_change_station(struct wiphy *wiphy,
6321 struct net_device *dev,
6322 uint8_t *mac,
6323 struct station_parameters *params)
6324#endif
6325{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306326 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006327 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6328 hdd_context_t *pHddCtx;
6329 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306330 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006331#ifdef FEATURE_WLAN_TDLS
6332 tCsrStaParams StaParams = { 0 };
6333 uint8_t isBufSta = 0;
6334 uint8_t isOffChannelSupported = 0;
6335#endif
6336 int ret;
6337
6338 ENTER();
6339
Anurag Chouhan6d760662016-02-20 16:05:43 +05306340 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006341 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6342 return -EINVAL;
6343 }
6344
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306345 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006346 TRACE_CODE_HDD_CHANGE_STATION,
6347 pAdapter->sessionId, params->listen_interval));
6348
6349 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6350 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306351 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006353
6354 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6355
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306356 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006357
6358 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6359 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6360 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
6361 status =
6362 hdd_softap_change_sta_state(pAdapter,
6363 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08006364 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006365
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306366 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306367 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006368 FL
6369 ("Not able to change TL state to AUTHENTICATED"));
6370 return -EINVAL;
6371 }
6372 }
6373 } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6374 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
6375#ifdef FEATURE_WLAN_TDLS
6376 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6377 StaParams.capability = params->capability;
6378 StaParams.uapsd_queues = params->uapsd_queues;
6379 StaParams.max_sp = params->max_sp;
6380
6381 /* Convert (first channel , number of channels) tuple to
6382 * the total list of channels. This goes with the assumption
6383 * that if the first channel is < 14, then the next channels
6384 * are an incremental of 1 else an incremental of 4 till the number
6385 * of channels.
6386 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306387 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006388 "%s: params->supported_channels_len: %d",
6389 __func__, params->supported_channels_len);
6390 if (0 != params->supported_channels_len) {
6391 int i = 0, j = 0, k = 0, no_of_channels = 0;
6392 int num_unique_channels;
6393 int next;
6394 for (i = 0;
6395 i < params->supported_channels_len
6396 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
6397 int wifi_chan_index;
6398 if (!wlan_hdd_is_duplicate_channel
6399 (StaParams.supported_channels, j,
6400 params->supported_channels[i])) {
6401 StaParams.
6402 supported_channels[j] =
6403 params->
6404 supported_channels[i];
6405 } else {
6406 continue;
6407 }
6408 wifi_chan_index =
6409 ((StaParams.supported_channels[j] <=
6410 HDD_CHANNEL_14) ? 1 : 4);
6411 no_of_channels =
6412 params->supported_channels[i + 1];
6413
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306414 QDF_TRACE(QDF_MODULE_ID_HDD,
6415 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006416 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d",
6417 __func__, i, j, k, j,
6418 StaParams.
6419 supported_channels[j],
6420 wifi_chan_index,
6421 no_of_channels);
6422 for (k = 1; k <= no_of_channels &&
6423 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
6424 k++) {
6425 next =
6426 StaParams.
6427 supported_channels[j] +
6428 wifi_chan_index;
6429 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
6430 StaParams.
6431 supported_channels[j
6432 +
6433 1]
6434 = next;
6435 } else {
6436 continue;
6437 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306438 QDF_TRACE(QDF_MODULE_ID_HDD,
6439 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006440 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d",
6441 __func__, i, j, k,
6442 j + 1,
6443 StaParams.
6444 supported_channels[j +
6445 1]);
6446 j += 1;
6447 }
6448 }
6449 num_unique_channels = j + 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306450 QDF_TRACE(QDF_MODULE_ID_HDD,
6451 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006452 "%s: Unique Channel List", __func__);
6453 for (i = 0; i < num_unique_channels; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306454 QDF_TRACE(QDF_MODULE_ID_HDD,
6455 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006456 "%s: StaParams.supported_channels[%d]: %d,",
6457 __func__, i,
6458 StaParams.
6459 supported_channels[i]);
6460 }
6461 if (MAX_CHANNEL < num_unique_channels)
6462 num_unique_channels = MAX_CHANNEL;
6463 StaParams.supported_channels_len =
6464 num_unique_channels;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306465 QDF_TRACE(QDF_MODULE_ID_HDD,
6466 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006467 "%s: After removing duplcates StaParams.supported_channels_len: %d",
6468 __func__,
6469 StaParams.supported_channels_len);
6470 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306471 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006472 params->supported_oper_classes,
6473 params->supported_oper_classes_len);
6474 StaParams.supported_oper_classes_len =
6475 params->supported_oper_classes_len;
6476
6477 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306478 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006479 params->ext_capab,
6480 sizeof(StaParams.extn_capability));
6481
6482 if (NULL != params->ht_capa) {
6483 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306484 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006485 sizeof(tSirHTCap));
6486 }
6487
6488 StaParams.supported_rates_len =
6489 params->supported_rates_len;
6490
6491 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
6492 * The supported_rates array , for all the structures propogating till Add Sta
6493 * to the firmware has to be modified , if the supplicant (ieee80211) is
6494 * modified to send more rates.
6495 */
6496
6497 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
6498 */
6499 if (StaParams.supported_rates_len >
6500 SIR_MAC_MAX_SUPP_RATES)
6501 StaParams.supported_rates_len =
6502 SIR_MAC_MAX_SUPP_RATES;
6503
6504 if (0 != StaParams.supported_rates_len) {
6505 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306506 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006507 params->supported_rates,
6508 StaParams.supported_rates_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306509 QDF_TRACE(QDF_MODULE_ID_HDD,
6510 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006511 "Supported Rates with Length %d",
6512 StaParams.supported_rates_len);
6513 for (i = 0; i < StaParams.supported_rates_len;
6514 i++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306515 QDF_TRACE(QDF_MODULE_ID_HDD,
6516 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006517 "[%d]: %0x", i,
6518 StaParams.supported_rates[i]);
6519 }
6520
6521 if (NULL != params->vht_capa) {
6522 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306523 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006524 params->vht_capa,
6525 sizeof(tSirVHTCap));
6526 }
6527
6528 if (0 != params->ext_capab_len) {
6529 /*Define A Macro : TODO Sunil */
6530 if ((1 << 4) & StaParams.extn_capability[3]) {
6531 isBufSta = 1;
6532 }
6533 /* TDLS Channel Switching Support */
6534 if ((1 << 6) & StaParams.extn_capability[3]) {
6535 isOffChannelSupported = 1;
6536 }
6537 }
6538
6539 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
6540 &StaParams,
6541 isBufSta,
6542 isOffChannelSupported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306543 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306544 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006545 FL
6546 ("wlan_hdd_tdls_set_peer_caps failed!"));
6547 return -EINVAL;
6548 }
6549
6550 status =
6551 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
6552 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306553 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306554 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006555 FL("wlan_hdd_tdls_add_station failed!"));
6556 return -EINVAL;
6557 }
6558 }
6559#endif
6560 }
6561 EXIT();
6562 return ret;
6563}
6564
6565/**
6566 * wlan_hdd_change_station() - cfg80211 change station handler function
6567 * @wiphy: Pointer to the wiphy structure
6568 * @dev: Pointer to the net device.
6569 * @mac: bssid
6570 * @params: Pointer to station parameters
6571 *
6572 * This is the cfg80211 change station handler function which invokes
6573 * the internal function @__wlan_hdd_change_station with
6574 * SSR protection.
6575 *
6576 * Return: 0 for success, error number on failure.
6577 */
6578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
6579static int wlan_hdd_change_station(struct wiphy *wiphy,
6580 struct net_device *dev,
6581 const u8 *mac,
6582 struct station_parameters *params)
6583#else
6584static int wlan_hdd_change_station(struct wiphy *wiphy,
6585 struct net_device *dev,
6586 u8 *mac,
6587 struct station_parameters *params)
6588#endif
6589{
6590 int ret;
6591
6592 cds_ssr_protect(__func__);
6593 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
6594 cds_ssr_unprotect(__func__);
6595
6596 return ret;
6597}
6598
6599/*
6600 * FUNCTION: __wlan_hdd_cfg80211_add_key
6601 * This function is used to initialize the key information
6602 */
6603static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6604 struct net_device *ndev,
6605 u8 key_index, bool pairwise,
6606 const u8 *mac_addr,
6607 struct key_params *params)
6608{
6609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6610 tCsrRoamSetKey setKey;
6611 int status;
6612 uint32_t roamId = 0xFF;
6613#ifndef WLAN_FEATURE_MBSSID
6614 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context;
6615#endif
6616 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306617 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 hdd_context_t *pHddCtx;
6619 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6620
6621 ENTER();
6622
Anurag Chouhan6d760662016-02-20 16:05:43 +05306623 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006624 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6625 return -EINVAL;
6626 }
6627
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306628 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006629 TRACE_CODE_HDD_CFG80211_ADD_KEY,
6630 pAdapter->sessionId, params->key_len));
6631 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6632 status = wlan_hdd_validate_context(pHddCtx);
6633
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306634 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006635 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006636
6637 hddLog(LOG1, FL("Device_mode %s(%d)"),
6638 hdd_device_mode_to_string(pAdapter->device_mode),
6639 pAdapter->device_mode);
6640
6641 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306642 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006643 __func__, key_index);
6644
6645 return -EINVAL;
6646 }
6647
6648 if (CSR_MAX_KEY_LEN < params->key_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306649 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006650 __func__, params->key_len);
6651
6652 return -EINVAL;
6653 }
6654
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306655 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006656 "%s: called with key index = %d & key length %d",
6657 __func__, key_index, params->key_len);
6658
6659 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306660 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006661 setKey.keyId = key_index;
6662 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306663 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006664
6665 switch (params->cipher) {
6666 case WLAN_CIPHER_SUITE_WEP40:
6667 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6668 break;
6669
6670 case WLAN_CIPHER_SUITE_WEP104:
6671 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
6672 break;
6673
6674 case WLAN_CIPHER_SUITE_TKIP:
6675 {
6676 u8 *pKey = &setKey.Key[0];
6677 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
6678
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306679 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680
6681 /*Supplicant sends the 32bytes key in this order
6682
6683 |--------------|----------|----------|
6684 | Tk1 |TX-MIC | RX Mic |
6685 |||--------------|----------|----------|
6686 <---16bytes---><--8bytes--><--8bytes-->
6687
6688 */
6689 /*Sme expects the 32 bytes key to be in the below order
6690
6691 |--------------|----------|----------|
6692 | Tk1 |RX-MIC | TX Mic |
6693 |||--------------|----------|----------|
6694 <---16bytes---><--8bytes--><--8bytes-->
6695 */
6696 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306697 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006698
6699 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306700 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006701
6702 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306703 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006704
6705 break;
6706 }
6707
6708 case WLAN_CIPHER_SUITE_CCMP:
6709 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
6710 break;
6711
6712#ifdef FEATURE_WLAN_WAPI
6713 case WLAN_CIPHER_SUITE_SMS4:
6714 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306715 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006716 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
6717 mac_addr, params->key,
6718 params->key_len);
6719 return 0;
6720 }
6721#endif
6722
6723#ifdef FEATURE_WLAN_ESE
6724 case WLAN_CIPHER_SUITE_KRK:
6725 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
6726 break;
6727#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6728 case WLAN_CIPHER_SUITE_BTK:
6729 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
6730 break;
6731#endif
6732#endif
6733
6734#ifdef WLAN_FEATURE_11W
6735 case WLAN_CIPHER_SUITE_AES_CMAC:
6736 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
6737 break;
6738#endif
6739
6740 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306741 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006742 __func__, params->cipher);
6743 return -EOPNOTSUPP;
6744 }
6745
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306746 hddLog(QDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006747 __func__, setKey.encType);
6748
6749 if (!pairwise) {
6750 /* set group key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306751 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006752 "%s- %d: setting Broadcast key", __func__, __LINE__);
6753 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05306754 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006755 } else {
6756 /* set pairwise key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306757 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006758 "%s- %d: setting pairwise key", __func__, __LINE__);
6759 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306760 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006761 }
6762 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise) {
6763 /* if a key is already installed, block all subsequent ones */
6764 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306765 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006766 "%s: IBSS key installed already", __func__);
6767 return 0;
6768 }
6769
6770 setKey.keyDirection = eSIR_TX_RX;
6771 /*Set the group key */
6772 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6773 pAdapter->sessionId, &setKey, &roamId);
6774
6775 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306776 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006777 "%s: sme_roam_set_key failed, returned %d",
6778 __func__, status);
6779 return -EINVAL;
6780 }
6781 /*Save the keys here and call sme_roam_set_key for setting
6782 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306783 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784 &setKey, sizeof(tCsrRoamSetKey));
6785
6786 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
6787 return status;
6788 }
6789 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6790 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6791 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6792 if (pHostapdState->bssState == BSS_START) {
6793#ifdef WLAN_FEATURE_MBSSID
6794 status =
6795 wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR
6796 (pAdapter), &setKey);
6797#else
6798 status = wlansap_set_key_sta(p_cds_context, &setKey);
6799#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306800 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306801 QDF_TRACE(QDF_MODULE_ID_HDD,
6802 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006803 "[%4d] wlansap_set_key_sta returned ERROR status= %d",
6804 __LINE__, status);
6805 }
6806 }
6807
6808 /* Save the key in ap ctx for use on START_BASS and restart */
6809 if (pairwise ||
6810 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
6811 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306812 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006813 sizeof(tCsrRoamSetKey));
6814 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306815 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006816 sizeof(tCsrRoamSetKey));
6817
6818 } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6819 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
6820 hdd_wext_state_t *pWextState =
6821 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6822 hdd_station_ctx_t *pHddStaCtx =
6823 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6824
6825 if (!pairwise) {
6826 /* set group key */
6827 if (pHddStaCtx->roam_info.deferKeyComplete) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306828 QDF_TRACE(QDF_MODULE_ID_HDD,
6829 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006830 "%s- %d: Perform Set key Complete",
6831 __func__, __LINE__);
6832 hdd_perform_roam_set_key_complete(pAdapter);
6833 }
6834 }
6835
6836 pWextState->roamProfile.Keys.KeyLength[key_index] =
6837 (u8) params->key_len;
6838
6839 pWextState->roamProfile.Keys.defaultIndex = key_index;
6840
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306841 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006842 KeyMaterial[key_index][0], params->key,
6843 params->key_len);
6844
6845 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6846
6847 hddLog(LOG2,
6848 FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"),
6849 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6850 setKey.keyDirection);
6851
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006852 /* The supplicant may attempt to set the PTK once pre-authentication
6853 is done. Save the key in the UMAC and include it in the ADD BSS
6854 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306855 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006856 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306857 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306858 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006859 "%s: Update PreAuth Key success", __func__);
6860 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306861 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306862 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006863 "%s: Update PreAuth Key failed", __func__);
6864 return -EINVAL;
6865 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006866
6867 /* issue set key request to SME */
6868 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6869 pAdapter->sessionId, &setKey, &roamId);
6870
6871 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306872 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006873 "%s: sme_roam_set_key failed, returned %d",
6874 __func__, status);
6875 pHddStaCtx->roam_info.roamingState =
6876 HDD_ROAM_STATE_NONE;
6877 return -EINVAL;
6878 }
6879
6880 /* in case of IBSS as there was no information available about WEP keys during
6881 * IBSS join, group key intialized with NULL key, so re-initialize group key
6882 * with correct value*/
6883 if ((eCSR_BSS_TYPE_START_IBSS ==
6884 pWextState->roamProfile.BSSType)
6885 &&
6886 !((IW_AUTH_KEY_MGMT_802_1X ==
6887 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
6888 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
6889 pHddStaCtx->conn_info.authType)
6890 )
6891 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
6892 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
6893 )
6894 ) {
6895 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05306896 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006897
6898 hddLog(LOG2,
6899 FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"),
6900 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6901 setKey.keyDirection);
6902
6903 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6904 pAdapter->sessionId, &setKey,
6905 &roamId);
6906
6907 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306908 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006909 "%s: sme_roam_set_key failed for group key (IBSS), returned %d",
6910 __func__, status);
6911 pHddStaCtx->roam_info.roamingState =
6912 HDD_ROAM_STATE_NONE;
6913 return -EINVAL;
6914 }
6915 }
6916 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306917 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006918 return 0;
6919}
6920
6921static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6922 struct net_device *ndev,
6923 u8 key_index, bool pairwise,
6924 const u8 *mac_addr,
6925 struct key_params *params)
6926{
6927 int ret;
6928 cds_ssr_protect(__func__);
6929 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
6930 mac_addr, params);
6931 cds_ssr_unprotect(__func__);
6932
6933 return ret;
6934}
6935
6936/*
6937 * FUNCTION: __wlan_hdd_cfg80211_get_key
6938 * This function is used to get the key information
6939 */
6940static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
6941 struct net_device *ndev,
6942 u8 key_index, bool pairwise,
6943 const u8 *mac_addr, void *cookie,
6944 void (*callback)(void *cookie,
6945 struct key_params *)
6946 )
6947{
6948 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6949 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6950 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
6951 struct key_params params;
6952
6953 ENTER();
6954
Anurag Chouhan6d760662016-02-20 16:05:43 +05306955 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006956 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6957 return -EINVAL;
6958 }
6959
6960 hddLog(LOG1, FL("Device_mode %s(%d)"),
6961 hdd_device_mode_to_string(pAdapter->device_mode),
6962 pAdapter->device_mode);
6963
6964 memset(&params, 0, sizeof(params));
6965
6966 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306967 hddLog(QDF_TRACE_LEVEL_ERROR, FL("invalid key index %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006968 key_index);
6969 return -EINVAL;
6970 }
6971
6972 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
6973 case eCSR_ENCRYPT_TYPE_NONE:
6974 params.cipher = IW_AUTH_CIPHER_NONE;
6975 break;
6976
6977 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
6978 case eCSR_ENCRYPT_TYPE_WEP40:
6979 params.cipher = WLAN_CIPHER_SUITE_WEP40;
6980 break;
6981
6982 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
6983 case eCSR_ENCRYPT_TYPE_WEP104:
6984 params.cipher = WLAN_CIPHER_SUITE_WEP104;
6985 break;
6986
6987 case eCSR_ENCRYPT_TYPE_TKIP:
6988 params.cipher = WLAN_CIPHER_SUITE_TKIP;
6989 break;
6990
6991 case eCSR_ENCRYPT_TYPE_AES:
6992 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6993 break;
6994
6995 default:
6996 params.cipher = IW_AUTH_CIPHER_NONE;
6997 break;
6998 }
6999
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307000 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007001 TRACE_CODE_HDD_CFG80211_GET_KEY,
7002 pAdapter->sessionId, params.cipher));
7003
7004 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
7005 params.seq_len = 0;
7006 params.seq = NULL;
7007 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
7008 callback(cookie, &params);
7009
7010 EXIT();
7011 return 0;
7012}
7013
7014static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7015 struct net_device *ndev,
7016 u8 key_index, bool pairwise,
7017 const u8 *mac_addr, void *cookie,
7018 void (*callback)(void *cookie,
7019 struct key_params *)
7020 )
7021{
7022 int ret;
7023
7024 cds_ssr_protect(__func__);
7025 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
7026 mac_addr, cookie, callback);
7027 cds_ssr_unprotect(__func__);
7028
7029 return ret;
7030}
7031
7032/**
7033 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
7034 * @wiphy: wiphy interface context
7035 * @ndev: pointer to net device
7036 * @key_index: Key index used in 802.11 frames
7037 * @unicast: true if it is unicast key
7038 * @multicast: true if it is multicast key
7039 *
7040 * This function is required for cfg80211_ops API.
7041 * It is used to delete the key information
7042 * Underlying hardware implementation does not have API to delete the
7043 * encryption key. It is automatically deleted when the peer is
7044 * removed. Hence this function currently does nothing.
7045 * Future implementation may interprete delete key operation to
7046 * replacing the key with a random junk value, effectively making it
7047 * useless.
7048 *
7049 * Return: status code, always 0.
7050 */
7051
7052static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7053 struct net_device *ndev,
7054 u8 key_index,
7055 bool pairwise, const u8 *mac_addr)
7056{
7057 EXIT();
7058 return 0;
7059}
7060
7061/**
7062 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
7063 * @wiphy: Pointer to wiphy structure.
7064 * @dev: Pointer to net_device structure.
7065 * @key_index: key index
7066 * @pairwise: pairwise
7067 * @mac_addr: mac address
7068 *
7069 * This is the cfg80211 delete key handler function which invokes
7070 * the internal function @__wlan_hdd_cfg80211_del_key with
7071 * SSR protection.
7072 *
7073 * Return: 0 for success, error number on failure.
7074 */
7075static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7076 struct net_device *dev,
7077 u8 key_index,
7078 bool pairwise, const u8 *mac_addr)
7079{
7080 int ret;
7081
7082 cds_ssr_protect(__func__);
7083 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
7084 pairwise, mac_addr);
7085 cds_ssr_unprotect(__func__);
7086
7087 return ret;
7088}
7089
7090/*
7091 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
7092 * This function is used to set the default tx key index
7093 */
7094static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7095 struct net_device *ndev,
7096 u8 key_index,
7097 bool unicast, bool multicast)
7098{
7099 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7100 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7101 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7102 hdd_context_t *pHddCtx;
7103 int status;
7104
7105 ENTER();
7106
Anurag Chouhan6d760662016-02-20 16:05:43 +05307107 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007108 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7109 return -EINVAL;
7110 }
7111
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307112 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007113 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
7114 pAdapter->sessionId, key_index));
7115
7116 hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"),
7117 hdd_device_mode_to_string(pAdapter->device_mode),
7118 pAdapter->device_mode, key_index);
7119
7120 if (CSR_MAX_NUM_KEY <= key_index) {
7121 hddLog(LOGE, FL("Invalid key index %d"), key_index);
7122 return -EINVAL;
7123 }
7124
7125 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7126 status = wlan_hdd_validate_context(pHddCtx);
7127
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307128 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007129 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007130
7131 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
7132 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
7133 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7134 pHddStaCtx->conn_info.ucEncryptionType) &&
7135 (eCSR_ENCRYPT_TYPE_AES !=
7136 pHddStaCtx->conn_info.ucEncryptionType)) {
7137 /* If default key index is not same as previous one,
7138 * then update the default key index */
7139
7140 tCsrRoamSetKey setKey;
7141 uint32_t roamId = 0xFF;
7142 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
7143
7144 hddLog(LOG2, FL("Default tx key index %d"), key_index);
7145
7146 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307147 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007148 setKey.keyId = key_index;
7149 setKey.keyLength = Keys->KeyLength[key_index];
7150
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307151 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007152 &Keys->KeyMaterial[key_index][0],
7153 Keys->KeyLength[key_index]);
7154
7155 setKey.keyDirection = eSIR_TX_RX;
7156
Anurag Chouhanc5548422016-02-24 18:33:27 +05307157 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007158 &pHddStaCtx->conn_info.bssId);
7159
7160 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
7161 pWextState->roamProfile.EncryptionType.
7162 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
7163 /* In the case of dynamic wep supplicant hardcodes DWEP type
7164 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
7165 * WEP-40 encryption. In this canse the key length is 5 but the
7166 * encryption type is 104 hence checking the key langht(5) and
7167 * encryption type(104) and switching encryption type to 40*/
7168 pWextState->roamProfile.EncryptionType.
7169 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7170 pWextState->roamProfile.mcEncryptionType.
7171 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7172 }
7173
7174 setKey.encType =
7175 pWextState->roamProfile.EncryptionType.
7176 encryptionType[0];
7177
7178 /* Issue set key request */
7179 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7180 pAdapter->sessionId, &setKey,
7181 &roamId);
7182
7183 if (0 != status) {
7184 hddLog(LOGE,
7185 FL("sme_roam_set_key failed, returned %d"),
7186 status);
7187 return -EINVAL;
7188 }
7189 }
7190 } else if (WLAN_HDD_SOFTAP == pAdapter->device_mode) {
7191 /* In SoftAp mode setting key direction for default mode */
7192 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7193 pWextState->roamProfile.EncryptionType.encryptionType[0])
7194 && (eCSR_ENCRYPT_TYPE_AES !=
7195 pWextState->roamProfile.EncryptionType.
7196 encryptionType[0])) {
7197 /* Saving key direction for default key index to TX default */
7198 hdd_ap_ctx_t *pAPCtx =
7199 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7200 pAPCtx->wepKey[key_index].keyDirection =
7201 eSIR_TX_DEFAULT;
7202 }
7203 }
7204
7205 EXIT();
7206 return status;
7207}
7208
7209static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7210 struct net_device *ndev,
7211 u8 key_index,
7212 bool unicast, bool multicast)
7213{
7214 int ret;
7215 cds_ssr_protect(__func__);
7216 ret =
7217 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
7218 multicast);
7219 cds_ssr_unprotect(__func__);
7220
7221 return ret;
7222}
7223
7224/**
7225 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
7226 * @pAdapter: Pointer to adapter
7227 * @pRoamInfo: Pointer to roam info
7228 *
7229 * Return: struct cfg80211_bss pointer
7230 */
7231struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
7232 tCsrRoamInfo *pRoamInfo)
7233{
7234 struct net_device *dev = pAdapter->dev;
7235 struct wireless_dev *wdev = dev->ieee80211_ptr;
7236 struct wiphy *wiphy = wdev->wiphy;
7237 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
7238 int chan_no;
7239 unsigned int freq;
7240 struct ieee80211_channel *chan;
7241 struct cfg80211_bss *bss = NULL;
7242
7243 ENTER();
7244
7245 if (NULL == pBssDesc) {
7246 hddLog(LOGE, FL("pBssDesc is NULL"));
7247 return bss;
7248 }
7249
7250 if (NULL == pRoamInfo->pProfile) {
7251 hddLog(LOGE, FL("Roam profile is NULL"));
7252 return bss;
7253 }
7254
7255 chan_no = pBssDesc->channelId;
7256
7257 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
7258 freq =
7259 ieee80211_channel_to_frequency(chan_no,
7260 IEEE80211_BAND_2GHZ);
7261 } else {
7262 freq =
7263 ieee80211_channel_to_frequency(chan_no,
7264 IEEE80211_BAND_5GHZ);
7265 }
7266
7267 chan = __ieee80211_get_channel(wiphy, freq);
7268
7269 if (!chan) {
7270 hddLog(LOGE, FL("chan pointer is NULL"));
7271 return NULL;
7272 }
7273
7274 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
7275 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
7276 ssId[0],
7277 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
Ryan Hsu535d16a2016-01-18 16:45:12 -08007278#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007279 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
Ryan Hsu535d16a2016-01-18 16:45:12 -08007280#else
7281 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
7282#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007283 if (bss == NULL) {
7284 hddLog(LOGE, FL("BSS not present"));
7285 } else {
7286 hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID "
7287 MAC_ADDRESS_STR),
7288 MAC_ADDR_ARRAY(pBssDesc->bssId));
7289 cfg80211_unlink_bss(wiphy, bss);
7290 }
7291 return bss;
7292}
7293
7294/**
7295 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
7296 * @pAdapter: Pointer to adapter
7297 * @bss_desc: Pointer to bss descriptor
7298 *
7299 * This function is used to inform the BSS details to nl80211 interface.
7300 *
7301 * Return: struct cfg80211_bss pointer
7302 */
7303static struct cfg80211_bss *
7304wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
7305 tSirBssDescription *bss_desc)
7306{
7307 /*
7308 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
7309 * already exists in bss data base of cfg80211 for that particular BSS
7310 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
7311 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
7312 * As of now there is no possibility to get the mgmt(probe response)
7313 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
7314 * and passing to cfg80211_inform_bss_frame.
7315 */
7316 struct net_device *dev = pAdapter->dev;
7317 struct wireless_dev *wdev = dev->ieee80211_ptr;
7318 struct wiphy *wiphy = wdev->wiphy;
7319 int chan_no = bss_desc->channelId;
7320#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7321 qcom_ie_age *qie_age = NULL;
7322 int ie_length =
7323 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
7324#else
7325 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
7326#endif
7327 const char *ie =
7328 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
7329 unsigned int freq;
7330 struct ieee80211_channel *chan;
7331 struct ieee80211_mgmt *mgmt = NULL;
7332 struct cfg80211_bss *bss_status = NULL;
7333 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
7334 int rssi = 0;
7335 hdd_context_t *pHddCtx;
7336 int status;
7337#ifdef CONFIG_CNSS
7338 struct timespec ts;
7339#endif
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007340 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007341
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307342 ENTER();
7343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007344 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7345 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307346 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007347 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007348
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007349 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007350 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
7351 if (!mgmt) {
7352 hddLog(LOGE, FL("memory allocation failed"));
7353 return NULL;
7354 }
7355
7356 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
7357
7358#ifdef CONFIG_CNSS
7359 /* Android does not want the timestamp from the frame.
7360 Instead it wants a monotonic increasing value */
7361 cnss_get_monotonic_boottime(&ts);
7362 mgmt->u.probe_resp.timestamp =
7363 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
7364#else
7365 /* keep old behavior for non-open source (for now) */
7366 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
7367 sizeof(bss_desc->timeStamp));
7368
7369#endif
7370
7371 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
7372 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
7373
7374#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7375 /* GPS Requirement: need age ie per entry. Using vendor specific. */
7376 /* Assuming this is the last IE, copy at the end */
7377 ie_length -= sizeof(qcom_ie_age);
7378 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
7379 qie_age->element_id = QCOM_VENDOR_IE_ID;
7380 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
7381 qie_age->oui_1 = QCOM_OUI1;
7382 qie_age->oui_2 = QCOM_OUI2;
7383 qie_age->oui_3 = QCOM_OUI3;
7384 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
7385 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +05307386 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007387 qie_age->tsf_delta = bss_desc->tsf_delta;
7388#endif
7389
7390 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
7391 if (bss_desc->fProbeRsp) {
7392 mgmt->frame_control |=
7393 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
7394 } else {
7395 mgmt->frame_control |=
7396 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
7397 }
7398
7399 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
7400 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
7401 freq =
7402 ieee80211_channel_to_frequency(chan_no,
7403 IEEE80211_BAND_2GHZ);
7404 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
7405 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
7406 freq =
7407 ieee80211_channel_to_frequency(chan_no,
7408 IEEE80211_BAND_5GHZ);
7409 } else {
7410 hddLog(LOGE, FL("Invalid chan_no %d"), chan_no);
7411 kfree(mgmt);
7412 return NULL;
7413 }
7414
7415 chan = __ieee80211_get_channel(wiphy, freq);
7416 /* When the band is changed on the fly using the GUI, three things are done
7417 * 1. scan abort
7418 * 2. flush scan results from cache
7419 * 3. update the band with the new band user specified (refer to the
7420 * hdd_set_band_helper function) as part of the scan abort, message will be
7421 * queued to PE and we proceed with flushing and changinh the band.
7422 * PE will stop the scanning further and report back the results what ever
7423 * it had till now by calling the call back function.
7424 * if the time between update band and scandone call back is sufficient
7425 * enough the band change reflects in SME, SME validates the channels
7426 * and discards the channels correponding to previous band and calls back
7427 * with zero bss results. but if the time between band update and scan done
7428 * callback is very small then band change will not reflect in SME and SME
7429 * reports to HDD all the channels correponding to previous band.this is due
7430 * to race condition.but those channels are invalid to the new band and so
7431 * this function __ieee80211_get_channel will return NULL.Each time we
7432 * report scan result with this pointer null warning kernel trace is printed.
7433 * if the scan results contain large number of APs continuosly kernel
7434 * warning trace is printed and it will lead to apps watch dog bark.
7435 * So drop the bss and continue to next bss.
7436 */
7437 if (chan == NULL) {
7438 hddLog(LOGE, FL("chan pointer is NULL"));
7439 kfree(mgmt);
7440 return NULL;
7441 }
7442
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007443 /* Based on .ini configuration, raw rssi can be reported for bss.
7444 * Raw rssi is typically used for estimating power.
7445 */
7446
7447 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
7448 bss_desc->rssi;
7449
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007450 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +05307451 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007452
7453 hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"),
7454 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
7455 (int)(rssi / 100));
7456
7457 bss_status =
7458 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
7459 GFP_KERNEL);
7460 kfree(mgmt);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307461 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007462 return bss_status;
7463}
7464
7465/**
7466 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
7467 * @pAdapter: Pointer to adapter
7468 * @pRoamInfo: Pointer to roam info
7469 *
7470 * This function is used to update the BSS data base of CFG8011
7471 *
7472 * Return: struct cfg80211_bss pointer
7473 */
7474struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
7475 tCsrRoamInfo *pRoamInfo)
7476{
7477 tCsrRoamConnectedProfile roamProfile;
7478 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7479 struct cfg80211_bss *bss = NULL;
7480
7481 ENTER();
7482
7483 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
7484 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
7485
7486 if (NULL != roamProfile.pBssDesc) {
7487 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7488 roamProfile.pBssDesc);
7489
7490 if (NULL == bss)
7491 hddLog(LOG1,
7492 FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL"));
7493
Naveen Rawatdf0a7e72016-01-06 18:35:53 -08007494 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007495 } else {
7496 hddLog(LOGE, FL("roamProfile.pBssDesc is NULL"));
7497 }
7498 EXIT();
7499 return bss;
7500}
7501/**
7502 * wlan_hdd_cfg80211_update_bss() - update bss
7503 * @wiphy: Pointer to wiphy
7504 * @pAdapter: Pointer to adapter
7505 * @scan_time: scan request timestamp
7506 *
7507 * Return: zero if success, non-zero otherwise
7508 */
7509int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
7510 hdd_adapter_t *pAdapter,
7511 uint32_t scan_time)
7512{
7513 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7514 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307515 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007516 tScanResultHandle pResult;
7517 struct cfg80211_bss *bss_status = NULL;
7518 hdd_context_t *pHddCtx;
7519 int ret;
7520
7521 ENTER();
7522
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307523 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007524 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
7525 NO_SESSION, pAdapter->sessionId));
7526
7527 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7528 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307529 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007530 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007531
7532 /* start getting scan results and populate cgf80211 BSS database */
7533 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
7534
7535 /* no scan results */
7536 if (NULL == pResult) {
7537 hddLog(LOGE, FL("No scan result Status %d"), status);
7538 return status;
7539 }
7540
7541 pScanResult = sme_scan_result_get_first(hHal, pResult);
7542
7543 while (pScanResult) {
7544 /*
7545 * - cfg80211_inform_bss() is not updating ie field of bss
7546 * entry if entry already exists in bss data base of cfg80211
7547 * for that particular BSS ID. Using cfg80211_inform_bss_frame
7548 * to update thebss entry instead of cfg80211_inform_bss,
7549 * But this call expects mgmt packet as input. As of now
7550 * there is no possibility to get the mgmt(probe response)
7551 * frame from PE, converting bss_desc to
7552 * ieee80211_mgmt(probe response) and passing to c
7553 * fg80211_inform_bss_frame.
7554 * - Update BSS only if beacon timestamp is later than
7555 * scan request timestamp.
7556 */
7557 if ((scan_time == 0) ||
7558 (scan_time <
7559 pScanResult->BssDescriptor.nReceivedTime)) {
7560 bss_status =
7561 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7562 &pScanResult->BssDescriptor);
7563
7564 if (NULL == bss_status) {
7565 hdd_info("NULL returned by cfg80211_inform_bss_frame");
7566 } else {
7567 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007568 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007569 bss_status);
7570 }
7571 } else {
7572 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
7573 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
7574 }
7575 pScanResult = sme_scan_result_get_next(hHal, pResult);
7576 }
7577
7578 sme_scan_result_purge(hHal, pResult);
7579 /*
7580 * For SAP mode, scan is invoked by hostapd during SAP start
7581 * if hostapd is restarted, we need to flush previous scan
7582 * result so that it will reflect environment change
7583 */
7584 if (pAdapter->device_mode == WLAN_HDD_SOFTAP
7585#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
7586 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
7587#endif
7588 )
7589 sme_scan_flush_result(hHal);
7590
7591 EXIT();
7592 return 0;
7593}
7594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007595/**
7596 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
7597 * @pAdapter: Pointer to adapter
7598 * @pRoamInfo: Pointer to roam info
7599 * @index: Index
7600 * @preauth: Preauth flag
7601 *
7602 * This function is used to notify the supplicant of a new PMKSA candidate.
7603 *
7604 * Return: 0 for success, non-zero for failure
7605 */
7606int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
7607 tCsrRoamInfo *pRoamInfo,
7608 int index, bool preauth)
7609{
7610#ifdef FEATURE_WLAN_OKC
7611 struct net_device *dev = pAdapter->dev;
7612 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
7613
7614 ENTER();
7615 hddLog(LOG1, FL("is going to notify supplicant of:"));
7616
7617 if (NULL == pRoamInfo) {
7618 hddLog(LOGP, FL("pRoamInfo is NULL"));
7619 return -EINVAL;
7620 }
7621
7622 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
7623 hddLog(LOG1, MAC_ADDRESS_STR,
7624 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
7625 cfg80211_pmksa_candidate_notify(dev, index,
7626 pRoamInfo->bssid.bytes,
7627 preauth, GFP_KERNEL);
7628 }
7629#endif /* FEATURE_WLAN_OKC */
7630 return 0;
7631}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007632
7633#ifdef FEATURE_WLAN_LFR_METRICS
7634/**
7635 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
7636 * @pAdapter: Pointer to adapter
7637 * @pRoamInfo: Pointer to roam info
7638 *
7639 * 802.11r/LFR metrics reporting function to report preauth initiation
7640 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307641 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007642 */
7643#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307644QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007645 tCsrRoamInfo *pRoamInfo)
7646{
7647 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7648 union iwreq_data wrqu;
7649
7650 ENTER();
7651
7652 if (NULL == pAdapter) {
7653 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307654 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007655 }
7656
7657 /* create the event */
7658 memset(&wrqu, 0, sizeof(wrqu));
7659 memset(metrics_notification, 0, sizeof(metrics_notification));
7660
7661 wrqu.data.pointer = metrics_notification;
7662 wrqu.data.length = scnprintf(metrics_notification,
7663 sizeof(metrics_notification),
7664 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
7665 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7666
7667 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7668 metrics_notification);
7669
7670 EXIT();
7671
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307672 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007673}
7674
7675/**
7676 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7677 * @pAdapter: Pointer to adapter
7678 * @pRoamInfo: Pointer to roam info
7679 * @preauth_status: Preauth status
7680 *
7681 * 802.11r/LFR metrics reporting function to report handover initiation
7682 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307683 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007684 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307685QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007686wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
7687 tCsrRoamInfo *pRoamInfo,
7688 bool preauth_status)
7689{
7690 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7691 union iwreq_data wrqu;
7692
7693 ENTER();
7694
7695 if (NULL == pAdapter) {
7696 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307697 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007698 }
7699
7700 /* create the event */
7701 memset(&wrqu, 0, sizeof(wrqu));
7702 memset(metrics_notification, 0, sizeof(metrics_notification));
7703
7704 scnprintf(metrics_notification, sizeof(metrics_notification),
7705 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
7706 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7707
7708 if (1 == preauth_status)
7709 strlcat(metrics_notification, " true",
7710 sizeof(metrics_notification));
7711 else
7712 strlcat(metrics_notification, " false",
7713 sizeof(metrics_notification));
7714
7715 wrqu.data.pointer = metrics_notification;
7716 wrqu.data.length = strlen(metrics_notification);
7717
7718 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7719 metrics_notification);
7720
7721 EXIT();
7722
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307723 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007724}
7725
7726/**
7727 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7728 * @pAdapter: Pointer to adapter
7729 * @pRoamInfo: Pointer to roam info
7730 *
7731 * 802.11r/LFR metrics reporting function to report handover initiation
7732 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307733 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007734 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307735QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007736 tCsrRoamInfo *pRoamInfo)
7737{
7738 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7739 union iwreq_data wrqu;
7740
7741 ENTER();
7742
7743 if (NULL == pAdapter) {
7744 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307745 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007746 }
7747
7748 /* create the event */
7749 memset(&wrqu, 0, sizeof(wrqu));
7750 memset(metrics_notification, 0, sizeof(metrics_notification));
7751
7752 wrqu.data.pointer = metrics_notification;
7753 wrqu.data.length = scnprintf(metrics_notification,
7754 sizeof(metrics_notification),
7755 "QCOM: LFR_PREAUTH_HANDOVER "
7756 MAC_ADDRESS_STR,
7757 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7758
7759 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7760 metrics_notification);
7761
7762 EXIT();
7763
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307764 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007765}
7766#endif
7767
7768/**
7769 * hdd_select_cbmode() - select channel bonding mode
7770 * @pAdapter: Pointer to adapter
7771 * @operatingChannel: Operating channel
7772 *
7773 * Return: none
7774 */
7775void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel)
7776{
7777 uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
7778 eHddDot11Mode hddDot11Mode = iniDot11Mode;
Amar Singhale4f28ee2015-10-21 14:36:56 -07007779 struct ch_params_s ch_params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007780 ch_params.ch_width =
7781 (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth;
7782
7783 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode);
7784 switch (iniDot11Mode) {
7785 case eHDD_DOT11_MODE_AUTO:
7786 case eHDD_DOT11_MODE_11ac:
7787 case eHDD_DOT11_MODE_11ac_ONLY:
7788#ifdef WLAN_FEATURE_11AC
7789 if (sme_is_feature_supported_by_fw(DOT11AC))
7790 hddDot11Mode = eHDD_DOT11_MODE_11ac;
7791 else
7792 hddDot11Mode = eHDD_DOT11_MODE_11n;
7793#else
7794 hddDot11Mode = eHDD_DOT11_MODE_11n;
7795#endif
7796 break;
7797 case eHDD_DOT11_MODE_11n:
7798 case eHDD_DOT11_MODE_11n_ONLY:
7799 hddDot11Mode = eHDD_DOT11_MODE_11n;
7800 break;
7801 default:
7802 hddDot11Mode = iniDot11Mode;
7803 break;
7804 }
7805 /* This call decides required channel bonding mode */
7806 sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal),
7807 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
7808 operationChannel, 0,
7809 &ch_params);
7810}
7811
7812
7813/*
7814 * FUNCTION: wlan_hdd_cfg80211_connect_start
7815 * wlan_hdd_cfg80211_connect_start() - start connection
7816 * @pAdapter: Pointer to adapter
7817 * @ssid: Pointer ot ssid
7818 * @ssid_len: Length of ssid
7819 * @bssid: Pointer to bssid
7820 * @operatingChannel: Operating channel
7821 *
7822 * This function is used to start the association process
7823 *
7824 * Return: 0 for success, non-zero for failure
7825 */
7826int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
7827 const u8 *ssid, size_t ssid_len,
7828 const u8 *bssid_hint, const u8 *bssid,
7829 u8 operatingChannel)
7830{
7831 int status = 0;
7832 hdd_wext_state_t *pWextState;
7833 hdd_context_t *pHddCtx;
7834 uint32_t roamId;
7835 tCsrRoamProfile *pRoamProfile;
7836 eCsrAuthType RSNAuthType;
7837 tSmeConfigParams *sme_config;
7838
7839 ENTER();
7840
7841 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7842 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7843
7844 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307845 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007846 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007847
7848 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
7849 hddLog(LOGE, FL("wrong SSID len"));
7850 return -EINVAL;
7851 }
7852
7853 pRoamProfile = &pWextState->roamProfile;
7854
7855 if (pRoamProfile) {
7856 hdd_station_ctx_t *pHddStaCtx;
7857 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7858
7859 if (HDD_WMM_USER_MODE_NO_QOS ==
7860 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
7861 /*QoS not enabled in cfg file */
7862 pRoamProfile->uapsd_mask = 0;
7863 } else {
7864 /*QoS enabled, update uapsd mask from cfg file */
7865 pRoamProfile->uapsd_mask =
7866 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
7867 }
7868
7869 pRoamProfile->SSIDs.numOfSSIDs = 1;
7870 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307871 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007872 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307873 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007874 ssid, ssid_len);
7875
7876 if (bssid) {
7877 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307878 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307879 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007880 /* Save BSSID in seperate variable as well, as RoamProfile
7881 BSSID is getting zeroed out in the association process. And in
7882 case of join failure we should send valid BSSID to supplicant
7883 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307884 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307885 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007886 } else if (bssid_hint) {
7887 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307888 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307889 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007890 /* Save BSSID in separate variable as well, as
7891 RoamProfile BSSID is getting zeroed out in the
7892 association process. And in case of join failure
7893 we should send valid BSSID to supplicant
7894 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307895 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307896 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007897 hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR),
7898 MAC_ADDR_ARRAY(bssid_hint));
7899 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307900 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307901 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007902 }
7903
7904 hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"),
7905 pRoamProfile->SSIDs.SSIDList->SSID.length,
7906 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
7907 operatingChannel);
7908
7909 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
7910 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
7911 /*set gen ie */
7912 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
7913 /*set auth */
7914 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
7915 }
7916#ifdef FEATURE_WLAN_WAPI
7917 if (pAdapter->wapi_info.nWapiMode) {
7918 hddLog(LOG1,
7919 FL("Setting WAPI AUTH Type and Encryption Mode values"));
7920 switch (pAdapter->wapi_info.wapiAuthMode) {
7921 case WAPI_AUTH_MODE_PSK:
7922 {
7923 hddLog(LOG1,
7924 FL("WAPI AUTH TYPE: PSK: %d"),
7925 pAdapter->wapi_info.wapiAuthMode);
7926 pRoamProfile->AuthType.authType[0] =
7927 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
7928 break;
7929 }
7930 case WAPI_AUTH_MODE_CERT:
7931 {
7932 hddLog(LOG1,
7933 FL("WAPI AUTH TYPE: CERT: %d"),
7934 pAdapter->wapi_info.wapiAuthMode);
7935 pRoamProfile->AuthType.authType[0] =
7936 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
7937 break;
7938 }
7939 } /* End of switch */
7940 if (pAdapter->wapi_info.wapiAuthMode ==
7941 WAPI_AUTH_MODE_PSK
7942 || pAdapter->wapi_info.wapiAuthMode ==
7943 WAPI_AUTH_MODE_CERT) {
7944 hddLog(LOG1,
7945 FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI"));
7946 pRoamProfile->AuthType.numEntries = 1;
7947 pRoamProfile->EncryptionType.numEntries = 1;
7948 pRoamProfile->EncryptionType.encryptionType[0] =
7949 eCSR_ENCRYPT_TYPE_WPI;
7950 pRoamProfile->mcEncryptionType.numEntries = 1;
7951 pRoamProfile->mcEncryptionType.
7952 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
7953 }
7954 }
7955#endif /* FEATURE_WLAN_WAPI */
7956#ifdef WLAN_FEATURE_GTK_OFFLOAD
7957 /* Initializing gtkOffloadReqParams */
7958 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7959 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
7960 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
7961 sizeof(tSirGtkOffloadParams));
7962 pHddStaCtx->gtkOffloadReqParams.ulFlags =
7963 GTK_OFFLOAD_DISABLE;
7964 }
7965#endif
7966 pRoamProfile->csrPersona = pAdapter->device_mode;
7967
7968 if (operatingChannel) {
7969 pRoamProfile->ChannelInfo.ChannelList =
7970 &operatingChannel;
7971 pRoamProfile->ChannelInfo.numOfChannels = 1;
7972 } else {
7973 pRoamProfile->ChannelInfo.ChannelList = NULL;
7974 pRoamProfile->ChannelInfo.numOfChannels = 0;
7975 }
7976 if ((WLAN_HDD_IBSS == pAdapter->device_mode)
7977 && operatingChannel) {
7978 /*
7979 * Need to post the IBSS power save parameters
7980 * to WMA. WMA will configure this parameters
7981 * to firmware if power save is enabled by the
7982 * firmware.
7983 */
7984 status = hdd_set_ibss_power_save_params(pAdapter);
7985
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307986 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007987 hddLog(LOGE,
7988 FL("Set IBSS Power Save Params Failed"));
7989 return -EINVAL;
7990 }
7991 hdd_select_cbmode(pAdapter, operatingChannel);
7992 }
7993
7994 if (pHddCtx->config->policy_manager_enabled &&
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08007995 (true == cds_is_connection_in_progress())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007996 hdd_err("Connection refused: conn in progress");
7997 return -EINVAL;
7998 }
7999
8000 /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect()
8001 * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state
8002 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
8003 * by either hdd_association_completion_handler() or hdd_dis_connect_handler() in sme_RoamCallback()
8004 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
8005 */
8006 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
8007 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) {
8008 hddLog(LOG1,
8009 FL("Set HDD connState to eConnectionState_Connecting"));
8010 hdd_conn_set_connection_state(pAdapter,
8011 eConnectionState_Connecting);
8012 }
8013
8014 /* After 8-way handshake supplicant should give the scan command
8015 * in that it update the additional IEs, But because of scan
8016 * enhancements, the supplicant is not issuing the scan command now.
8017 * So the unicast frames which are sent from the host are not having
8018 * the additional IEs. If it is P2P CLIENT and there is no additional
8019 * IE present in roamProfile, then use the addtional IE form scan_info
8020 */
8021
8022 if ((pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
8023 (!pRoamProfile->pAddIEScan)) {
8024 pRoamProfile->pAddIEScan =
8025 &pAdapter->scan_info.scanAddIE.addIEdata[0];
8026 pRoamProfile->nAddIEScanLength =
8027 pAdapter->scan_info.scanAddIE.length;
8028 }
8029 /*
8030 * When policy manager is enabled from ini file, we shouldn't
8031 * check for other concurrency rules.
8032 */
8033 if (!pHddCtx->config->policy_manager_enabled) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008034 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008035 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008036 pAdapter, pRoamProfile, &roamId))
8037 return 0;
8038 }
8039
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308040 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008041 if (!sme_config) {
8042 hdd_err("unable to allocate sme_config");
8043 return -ENOMEM;
8044 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308045 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008046 sme_get_config_param(pHddCtx->hHal, sme_config);
8047 /* These values are not sessionized. So, any change in these SME
8048 * configs on an older or parallel interface will affect the
8049 * cb mode. So, restoring the default INI params before starting
8050 * interfaces such as sta, cli etc.,
8051 */
8052 sme_config->csrConfig.channelBondingMode5GHz =
8053 pHddCtx->config->nChannelBondingMode5GHz;
8054 sme_config->csrConfig.channelBondingMode24GHz =
8055 pHddCtx->config->nChannelBondingMode24GHz;
8056 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308057 qdf_mem_free(sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008058
8059 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8060 pAdapter->sessionId, pRoamProfile,
8061 &roamId);
8062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308063 if ((QDF_STATUS_SUCCESS != status) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008064 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
8065 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
8066 hddLog(LOGE,
8067 FL("sme_roam_connect (session %d) failed with "
8068 "status %d. -> NotConnected"),
8069 pAdapter->sessionId, status);
8070 /* change back to NotAssociated */
8071 hdd_conn_set_connection_state(pAdapter,
8072 eConnectionState_NotConnected);
8073 }
8074
8075 pRoamProfile->ChannelInfo.ChannelList = NULL;
8076 pRoamProfile->ChannelInfo.numOfChannels = 0;
8077
8078 } else {
8079 hddLog(LOGE, FL("No valid Roam profile"));
8080 return -EINVAL;
8081 }
8082 EXIT();
8083 return status;
8084}
8085
8086/**
8087 * wlan_hdd_cfg80211_set_auth_type() - set auth type
8088 * @pAdapter: Pointer to adapter
8089 * @auth_type: Auth type
8090 *
8091 * This function is used to set the authentication type (OPEN/SHARED).
8092 *
8093 * Return: 0 for success, non-zero for failure
8094 */
8095static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
8096 enum nl80211_auth_type auth_type)
8097{
8098 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8099 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8100
8101 ENTER();
8102
8103 /*set authentication type */
8104 switch (auth_type) {
8105 case NL80211_AUTHTYPE_AUTOMATIC:
8106 hddLog(LOG1,
8107 FL("set authentication type to AUTOSWITCH"));
8108 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
8109 break;
8110
8111 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008112 case NL80211_AUTHTYPE_FT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008113 hddLog(LOG1,
8114 FL("set authentication type to OPEN"));
8115 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8116 break;
8117
8118 case NL80211_AUTHTYPE_SHARED_KEY:
8119 hddLog(LOG1,
8120 FL("set authentication type to SHARED"));
8121 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
8122 break;
8123#ifdef FEATURE_WLAN_ESE
8124 case NL80211_AUTHTYPE_NETWORK_EAP:
8125 hddLog(LOG1,
8126 FL("set authentication type to CCKM WPA"));
8127 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
8128 break;
8129#endif
8130
8131 default:
8132 hddLog(LOGE,
8133 FL("Unsupported authentication type %d"), auth_type);
8134 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
8135 return -EINVAL;
8136 }
8137
8138 pWextState->roamProfile.AuthType.authType[0] =
8139 pHddStaCtx->conn_info.authType;
8140 return 0;
8141}
8142
8143/**
8144 * wlan_hdd_set_akm_suite() - set key management type
8145 * @pAdapter: Pointer to adapter
8146 * @key_mgmt: Key management type
8147 *
8148 * This function is used to set the key mgmt type(PSK/8021x).
8149 *
8150 * Return: 0 for success, non-zero for failure
8151 */
8152static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
8153{
8154 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8155
8156 ENTER();
8157
8158#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
8159#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
8160 /*set key mgmt type */
8161 switch (key_mgmt) {
8162 case WLAN_AKM_SUITE_PSK:
8163 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008164 case WLAN_AKM_SUITE_FT_PSK:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008165 hddLog(LOG1, FL("setting key mgmt type to PSK"));
8166 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
8167 break;
8168
8169 case WLAN_AKM_SUITE_8021X_SHA256:
8170 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008171 case WLAN_AKM_SUITE_FT_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008172 hddLog(LOG1,
8173 FL("setting key mgmt type to 8021x"));
8174 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8175 break;
8176#ifdef FEATURE_WLAN_ESE
8177#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
8178#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
8179 case WLAN_AKM_SUITE_CCKM:
8180 hddLog(LOG1,
8181 FL("setting key mgmt type to CCKM"));
8182 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
8183 break;
8184#endif
8185#ifndef WLAN_AKM_SUITE_OSEN
8186#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
8187#endif
8188 case WLAN_AKM_SUITE_OSEN:
8189 hddLog(LOG1,
8190 FL("setting key mgmt type to OSEN"));
8191 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8192 break;
8193
8194 default:
8195 hddLog(LOGE,
8196 FL("Unsupported key mgmt type %d"), key_mgmt);
8197 return -EINVAL;
8198
8199 }
8200 return 0;
8201}
8202
8203/**
8204 * wlan_hdd_cfg80211_set_cipher() - set encryption type
8205 * @pAdapter: Pointer to adapter
8206 * @cipher: Cipher type
8207 * @ucast: Unicast flag
8208 *
8209 * This function is used to set the encryption type
8210 * (NONE/WEP40/WEP104/TKIP/CCMP).
8211 *
8212 * Return: 0 for success, non-zero for failure
8213 */
8214static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
8215 u32 cipher, bool ucast)
8216{
8217 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8218 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8219 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8220
8221 ENTER();
8222
8223 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008224 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008225 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8226 } else {
8227
8228 /*set encryption method */
8229 switch (cipher) {
8230 case IW_AUTH_CIPHER_NONE:
8231 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8232 break;
8233
8234 case WLAN_CIPHER_SUITE_WEP40:
8235 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
8236 break;
8237
8238 case WLAN_CIPHER_SUITE_WEP104:
8239 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
8240 break;
8241
8242 case WLAN_CIPHER_SUITE_TKIP:
8243 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
8244 break;
8245
8246 case WLAN_CIPHER_SUITE_CCMP:
8247 encryptionType = eCSR_ENCRYPT_TYPE_AES;
8248 break;
8249#ifdef FEATURE_WLAN_WAPI
8250 case WLAN_CIPHER_SUITE_SMS4:
8251 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
8252 break;
8253#endif
8254
8255#ifdef FEATURE_WLAN_ESE
8256 case WLAN_CIPHER_SUITE_KRK:
8257 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
8258 break;
8259#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8260 case WLAN_CIPHER_SUITE_BTK:
8261 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
8262 break;
8263#endif
8264#endif
8265 default:
8266 hddLog(LOGE,
8267 FL("Unsupported cipher type %d"), cipher);
8268 return -EOPNOTSUPP;
8269 }
8270 }
8271
8272 if (ucast) {
8273 hddLog(LOG1,
8274 FL("setting unicast cipher type to %d"), encryptionType);
8275 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
8276 pWextState->roamProfile.EncryptionType.numEntries = 1;
8277 pWextState->roamProfile.EncryptionType.encryptionType[0] =
8278 encryptionType;
8279 } else {
8280 hddLog(LOG1,
8281 FL("setting mcast cipher type to %d"), encryptionType);
8282 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
8283 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
8284 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
8285 encryptionType;
8286 }
8287
8288 return 0;
8289}
8290
8291/**
8292 * wlan_hdd_cfg80211_set_ie() - set IEs
8293 * @pAdapter: Pointer to adapter
8294 * @ie: Pointer ot ie
8295 * @ie: IE length
8296 *
8297 * Return: 0 for success, non-zero for failure
8298 */
8299int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
8300 size_t ie_len)
8301{
8302 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8303 const uint8_t *genie = ie;
8304 uint16_t remLen = ie_len;
8305#ifdef FEATURE_WLAN_WAPI
8306 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
8307 u16 *tmp;
8308 uint16_t akmsuiteCount;
8309 int *akmlist;
8310#endif
8311 ENTER();
8312
8313 /* clear previous assocAddIE */
8314 pWextState->assocAddIE.length = 0;
8315 pWextState->roamProfile.bWPSAssociation = false;
8316 pWextState->roamProfile.bOSENAssociation = false;
8317
8318 while (remLen >= 2) {
8319 uint16_t eLen = 0;
8320 uint8_t elementId;
8321 elementId = *genie++;
8322 eLen = *genie++;
8323 remLen -= 2;
8324
8325 hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), elementId, eLen);
8326
8327 switch (elementId) {
8328 case DOT11F_EID_WPA:
8329 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
8330 hddLog(LOGE, FL("Invalid WPA IE"));
8331 return -EINVAL;
8332 } else if (0 ==
8333 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
8334 uint16_t curAddIELen =
8335 pWextState->assocAddIE.length;
8336 hddLog(LOG1,
8337 FL("Set WPS IE(len %d)"), eLen + 2);
8338
8339 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8340 (pWextState->assocAddIE.length + eLen)) {
8341 hddLog(LOGE,
8342 FL("Cannot accommodate assocAddIE. Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308343 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008344 return -ENOMEM;
8345 }
8346 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8347 memcpy(pWextState->assocAddIE.addIEdata +
8348 curAddIELen, genie - 2, eLen + 2);
8349 pWextState->assocAddIE.length += eLen + 2;
8350
8351 pWextState->roamProfile.bWPSAssociation = true;
8352 pWextState->roamProfile.pAddIEAssoc =
8353 pWextState->assocAddIE.addIEdata;
8354 pWextState->roamProfile.nAddIEAssocLength =
8355 pWextState->assocAddIE.length;
8356 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
8357 hddLog(LOG1,
8358 FL("Set WPA IE (len %d)"), eLen + 2);
8359 memset(pWextState->WPARSNIE, 0,
8360 MAX_WPA_RSN_IE_LEN);
8361 memcpy(pWextState->WPARSNIE, genie - 2,
8362 (eLen + 2));
8363 pWextState->roamProfile.pWPAReqIE =
8364 pWextState->WPARSNIE;
8365 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
8366 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
8367 P2P_OUI_TYPE_SIZE))) {
8368 uint16_t curAddIELen =
8369 pWextState->assocAddIE.length;
8370 hddLog(LOG1,
8371 FL("Set P2P IE(len %d)"), eLen + 2);
8372
8373 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8374 (pWextState->assocAddIE.length + eLen)) {
8375 hddLog(LOGE,
8376 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308377 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008378 return -ENOMEM;
8379 }
8380 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8381 memcpy(pWextState->assocAddIE.addIEdata +
8382 curAddIELen, genie - 2, eLen + 2);
8383 pWextState->assocAddIE.length += eLen + 2;
8384
8385 pWextState->roamProfile.pAddIEAssoc =
8386 pWextState->assocAddIE.addIEdata;
8387 pWextState->roamProfile.nAddIEAssocLength =
8388 pWextState->assocAddIE.length;
8389 }
8390#ifdef WLAN_FEATURE_WFD
8391 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
8392 WFD_OUI_TYPE_SIZE)) &&
8393 /* Consider WFD IE, only for P2P Client */
8394 (WLAN_HDD_P2P_CLIENT ==
8395 pAdapter->device_mode)) {
8396 uint16_t curAddIELen =
8397 pWextState->assocAddIE.length;
8398 hddLog(LOG1,
8399 FL("Set WFD IE(len %d)"), eLen + 2);
8400
8401 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8402 (pWextState->assocAddIE.length + eLen)) {
8403 hddLog(LOGE,
8404 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308405 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008406 return -ENOMEM;
8407 }
8408 /* WFD IE is saved to Additional IE ; it should
8409 * be accumulated to handle WPS IE + P2P IE +
8410 * WFD IE */
8411 memcpy(pWextState->assocAddIE.addIEdata +
8412 curAddIELen, genie - 2, eLen + 2);
8413 pWextState->assocAddIE.length += eLen + 2;
8414
8415 pWextState->roamProfile.pAddIEAssoc =
8416 pWextState->assocAddIE.addIEdata;
8417 pWextState->roamProfile.nAddIEAssocLength =
8418 pWextState->assocAddIE.length;
8419 }
8420#endif
8421 /* Appending HS 2.0 Indication Element in Assiciation Request */
8422 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
8423 HS20_OUI_TYPE_SIZE))) {
8424 uint16_t curAddIELen =
8425 pWextState->assocAddIE.length;
8426 hddLog(LOG1,
8427 FL("Set HS20 IE(len %d)"), eLen + 2);
8428
8429 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8430 (pWextState->assocAddIE.length + eLen)) {
8431 hddLog(LOGE,
8432 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308433 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008434 return -ENOMEM;
8435 }
8436 memcpy(pWextState->assocAddIE.addIEdata +
8437 curAddIELen, genie - 2, eLen + 2);
8438 pWextState->assocAddIE.length += eLen + 2;
8439
8440 pWextState->roamProfile.pAddIEAssoc =
8441 pWextState->assocAddIE.addIEdata;
8442 pWextState->roamProfile.nAddIEAssocLength =
8443 pWextState->assocAddIE.length;
8444 }
8445 /* Appending OSEN Information Element in Assiciation Request */
8446 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
8447 OSEN_OUI_TYPE_SIZE))) {
8448 uint16_t curAddIELen =
8449 pWextState->assocAddIE.length;
8450 hddLog(LOG1,
8451 FL("Set OSEN IE(len %d)"), eLen + 2);
8452
8453 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8454 (pWextState->assocAddIE.length + eLen)) {
8455 hddLog(LOGE,
8456 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308457 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008458 return -ENOMEM;
8459 }
8460 memcpy(pWextState->assocAddIE.addIEdata +
8461 curAddIELen, genie - 2, eLen + 2);
8462 pWextState->assocAddIE.length += eLen + 2;
8463
8464 pWextState->roamProfile.bOSENAssociation = true;
8465 pWextState->roamProfile.pAddIEAssoc =
8466 pWextState->assocAddIE.addIEdata;
8467 pWextState->roamProfile.nAddIEAssocLength =
8468 pWextState->assocAddIE.length;
8469 } else {
8470 uint16_t add_ie_len =
8471 pWextState->assocAddIE.length;
8472
8473 hdd_info("Set OSEN IE(len %d)", eLen + 2);
8474
8475 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8476 (pWextState->assocAddIE.length + eLen)) {
8477 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308478 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008479 return -ENOMEM;
8480 }
8481
8482 memcpy(pWextState->assocAddIE.addIEdata +
8483 add_ie_len, genie - 2, eLen + 2);
8484 pWextState->assocAddIE.length += eLen + 2;
8485
8486 pWextState->roamProfile.pAddIEAssoc =
8487 pWextState->assocAddIE.addIEdata;
8488 pWextState->roamProfile.nAddIEAssocLength =
8489 pWextState->assocAddIE.length;
8490 }
8491 break;
8492 case DOT11F_EID_RSN:
8493 hddLog(LOG1, FL("Set RSN IE(len %d)"), eLen + 2);
8494 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
8495 memcpy(pWextState->WPARSNIE, genie - 2,
8496 (eLen + 2));
8497 pWextState->roamProfile.pRSNReqIE =
8498 pWextState->WPARSNIE;
8499 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
8500 break;
8501 /*
8502 * Appending Extended Capabilities with Interworking bit set
8503 * in Assoc Req.
8504 *
8505 * In assoc req this EXT Cap will only be taken into account if
8506 * interworkingService bit is set to 1. Currently
8507 * driver is only interested in interworkingService capability
8508 * from supplicant. If in future any other EXT Cap info is
8509 * required from supplicat, it needs to be handled while
8510 * sending Assoc Req in LIM.
8511 */
8512 case DOT11F_EID_EXTCAP:
8513 {
8514 uint16_t curAddIELen =
8515 pWextState->assocAddIE.length;
8516 hddLog(LOG1,
8517 FL("Set Extended CAPS IE(len %d)"), eLen + 2);
8518
8519 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8520 (pWextState->assocAddIE.length + eLen)) {
8521 hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308522 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008523 return -ENOMEM;
8524 }
8525 memcpy(pWextState->assocAddIE.addIEdata +
8526 curAddIELen, genie - 2, eLen + 2);
8527 pWextState->assocAddIE.length += eLen + 2;
8528
8529 pWextState->roamProfile.pAddIEAssoc =
8530 pWextState->assocAddIE.addIEdata;
8531 pWextState->roamProfile.nAddIEAssocLength =
8532 pWextState->assocAddIE.length;
8533 break;
8534 }
8535#ifdef FEATURE_WLAN_WAPI
8536 case WLAN_EID_WAPI:
8537 /* Setting WAPI Mode to ON=1 */
8538 pAdapter->wapi_info.nWapiMode = 1;
8539 hddLog(LOG1,
8540 FL("WAPI MODE IS %u"), pAdapter->wapi_info.nWapiMode);
8541 tmp = (u16 *) ie;
8542 tmp = tmp + 2; /* Skip element Id and Len, Version */
8543 akmsuiteCount = WPA_GET_LE16(tmp);
8544 tmp = tmp + 1;
8545 akmlist = (int *)(tmp);
8546 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
8547 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
8548 } else {
8549 hddLog(LOGE,
8550 FL("Invalid akmSuite count"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308551 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008552 return -EINVAL;
8553 }
8554
8555 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
8556 hddLog(LOG1,
8557 FL("WAPI AUTH MODE SET TO PSK"));
8558 pAdapter->wapi_info.wapiAuthMode =
8559 WAPI_AUTH_MODE_PSK;
8560 }
8561 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
8562 hddLog(LOG1,
8563 FL("WAPI AUTH MODE SET TO CERTIFICATE"));
8564 pAdapter->wapi_info.wapiAuthMode =
8565 WAPI_AUTH_MODE_CERT;
8566 }
8567 break;
8568#endif
8569 default:
8570 hddLog(LOGE,
8571 FL("Set UNKNOWN IE %X"), elementId);
8572 /* when Unknown IE is received we should break and continue
8573 * to the next IE in the buffer instead we were returning
8574 * so changing this to break */
8575 break;
8576 }
8577 genie += eLen;
8578 remLen -= eLen;
8579 }
8580 EXIT();
8581 return 0;
8582}
8583
8584/**
8585 * hdd_is_wpaie_present() - check for WPA ie
8586 * @ie: Pointer to ie
8587 * @ie_len: Ie length
8588 *
8589 * Parse the received IE to find the WPA IE
8590 *
8591 * Return: true if wpa ie is found else false
8592 */
8593static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
8594{
8595 uint8_t eLen = 0;
8596 uint16_t remLen = ie_len;
8597 uint8_t elementId = 0;
8598
8599 while (remLen >= 2) {
8600 elementId = *ie++;
8601 eLen = *ie++;
8602 remLen -= 2;
8603 if (eLen > remLen) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308604 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008605 "%s: IE length is wrong %d", __func__, eLen);
8606 return false;
8607 }
8608 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
8609 /* OUI - 0x00 0X50 0XF2
8610 * WPA Information Element - 0x01
8611 * WPA version - 0x01
8612 */
8613 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
8614 return true;
8615 }
8616 ie += eLen;
8617 remLen -= eLen;
8618 }
8619 return false;
8620}
8621
8622/**
8623 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
8624 * @pAdapter: Pointer to adapter
8625 * @req: Pointer to security parameters
8626 *
8627 * Return: 0 for success, non-zero for failure
8628 */
8629int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
8630 struct cfg80211_connect_params *req)
8631{
8632 int status = 0;
8633 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8634 ENTER();
8635
8636 /*set wpa version */
8637 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
8638
8639 if (req->crypto.wpa_versions) {
8640 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
8641 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
8642 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
8643 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
8644 }
8645 }
8646
8647 hddLog(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion);
8648
8649 /*set authentication type */
8650 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
8651
8652 if (0 > status) {
8653 hddLog(LOGE, FL("failed to set authentication type "));
8654 return status;
8655 }
8656
8657 /*set key mgmt type */
8658 if (req->crypto.n_akm_suites) {
8659 status =
8660 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
8661 if (0 > status) {
8662 hddLog(LOGE, FL("failed to set akm suite"));
8663 return status;
8664 }
8665 }
8666
8667 /*set pairwise cipher type */
8668 if (req->crypto.n_ciphers_pairwise) {
8669 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
8670 req->crypto.
8671 ciphers_pairwise[0],
8672 true);
8673 if (0 > status) {
8674 hddLog(LOGE, FL("failed to set unicast cipher type"));
8675 return status;
8676 }
8677 } else {
8678 /*Reset previous cipher suite to none */
8679 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
8680 if (0 > status) {
8681 hddLog(LOGE, FL("failed to set unicast cipher type"));
8682 return status;
8683 }
8684 }
8685
8686 /*set group cipher type */
8687 status =
8688 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
8689 false);
8690
8691 if (0 > status) {
8692 hddLog(LOGE, FL("failed to set mcast cipher type"));
8693 return status;
8694 }
8695#ifdef WLAN_FEATURE_11W
8696 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
8697#endif
8698
8699 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
8700 if (req->ie_len) {
8701 status =
8702 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
8703 if (0 > status) {
8704 hddLog(LOGE, FL("failed to parse the WPA/RSN IE"));
8705 return status;
8706 }
8707 }
8708
8709 /*incase of WEP set default key information */
8710 if (req->key && req->key_len) {
8711 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
8712 || (WLAN_CIPHER_SUITE_WEP104 ==
8713 req->crypto.ciphers_pairwise[0])
8714 ) {
8715 if (IW_AUTH_KEY_MGMT_802_1X
8716 ==
8717 (pWextState->
8718 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
8719 hddLog(LOGE,
8720 FL("Dynamic WEP not supported"));
8721 return -EOPNOTSUPP;
8722 } else {
8723 u8 key_len = req->key_len;
8724 u8 key_idx = req->key_idx;
8725
8726 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
8727 key_len)
8728 && (CSR_MAX_NUM_KEY > key_idx)
8729 ) {
8730 hddLog(LOG1,
8731 FL("setting default wep key, key_idx = %hu key_len %hu"),
8732 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308733 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008734 Keys.
8735 KeyMaterial[key_idx][0],
8736 req->key, key_len);
8737 pWextState->roamProfile.Keys.
8738 KeyLength[key_idx] = (u8) key_len;
8739 pWextState->roamProfile.Keys.
8740 defaultIndex = (u8) key_idx;
8741 }
8742 }
8743 }
8744 }
8745
8746 return status;
8747}
8748
8749/**
8750 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
8751 * @pAdapter: Pointer to adapter
8752 *
8753 * This function is used to disconnect from previous connection
8754 *
8755 * Return: 0 for success, non-zero for failure
8756 */
8757static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
8758{
8759 unsigned long rc;
8760 hdd_station_ctx_t *pHddStaCtx;
8761 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308762 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008763
8764 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8765
8766 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
8767
8768 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +05308769 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
8770 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
8771 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008772 hdd_conn_set_connection_state(pAdapter,
8773 eConnectionState_Disconnecting);
8774 /* Issue disconnect to CSR */
8775 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308776
8777 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8778 pAdapter->sessionId,
8779 eCSR_DISCONNECT_REASON_UNSPECIFIED);
8780 /*
8781 * Wait here instead of returning directly, this will block the
8782 * next connect command and allow processing of the scan for
8783 * ssid and the previous connect command in CSR. Else we might
8784 * hit some race conditions leading to SME and HDD out of sync.
8785 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308786 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308787 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
8788 } else if (0 != status) {
8789 hdd_err("csrRoamDisconnect failure, returned %d",
8790 (int)status);
8791 pHddStaCtx->staDebugState = status;
8792 result = -EINVAL;
8793 goto disconnected;
8794 }
8795
8796 rc = wait_for_completion_timeout(
8797 &pAdapter->disconnect_comp_var,
8798 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308799 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308800 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
8801 pAdapter->sessionId, pHddStaCtx->staDebugState);
8802 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008803 }
8804 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308805 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008806 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308807 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008808 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308809 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008810 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308811 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008812 }
8813 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308814disconnected:
8815 hdd_info("Set HDD connState to eConnectionState_NotConnected");
8816 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
8817 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008818}
8819
8820/**
8821 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
8822 * @wiphy: Pointer to wiphy
8823 * @dev: Pointer to network device
8824 * @req: Pointer to cfg80211 connect request
8825 *
8826 * This function is used to start the association process
8827 *
8828 * Return: 0 for success, non-zero for failure
8829 */
8830static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8831 struct net_device *ndev,
8832 struct cfg80211_connect_params *req)
8833{
8834 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05308835 u16 channel;
8836#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
8837 const u8 *bssid_hint = req->bssid_hint;
8838#else
8839 const u8 *bssid_hint = NULL;
8840#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008841 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8842 hdd_context_t *pHddCtx;
8843
8844 ENTER();
8845
Anurag Chouhan6d760662016-02-20 16:05:43 +05308846 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008847 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8848 return -EINVAL;
8849 }
8850
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308851 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852 TRACE_CODE_HDD_CFG80211_CONNECT,
8853 pAdapter->sessionId, pAdapter->device_mode));
8854 hddLog(LOG1, FL("Device_mode %s(%d)"),
8855 hdd_device_mode_to_string(pAdapter->device_mode),
8856 pAdapter->device_mode);
8857
8858 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION &&
8859 pAdapter->device_mode != WLAN_HDD_P2P_CLIENT) {
8860 hddLog(LOGE, FL("Device_mode %s(%d) is not supported"),
8861 hdd_device_mode_to_string(pAdapter->device_mode),
8862 pAdapter->device_mode);
8863 return -EINVAL;
8864 }
8865
8866 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8867 if (!pHddCtx) {
8868 hddLog(LOGE, FL("HDD context is null"));
8869 return -EINVAL;
8870 }
8871
8872 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308873 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008874 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008875 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008876 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008877 cds_convert_device_mode_to_hdd_type(
8878 pAdapter->device_mode),
8879 req->channel->hw_value, HW_MODE_20_MHZ)) {
8880 hdd_err("This concurrency combination is not allowed");
8881 return -ECONNREFUSED;
8882 }
8883 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008884 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008885 cds_convert_device_mode_to_hdd_type(
8886 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
8887 hdd_err("This concurrency combination is not allowed");
8888 return -ECONNREFUSED;
8889 }
8890 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008891 wlan_hdd_disable_roaming(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008892
8893 /*Try disconnecting if already in connected state */
8894 status = wlan_hdd_try_disconnect(pAdapter);
8895 if (0 > status) {
8896 hddLog(LOGE,
8897 FL("Failed to disconnect the existing connection"));
8898 return -EALREADY;
8899 }
8900
8901 /*initialise security parameters */
8902 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
8903
8904 if (0 > status) {
8905 hddLog(LOGE,
8906 FL("failed to set security params"));
8907 return status;
8908 }
8909
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05308910 if (req->channel)
8911 channel = req->channel->hw_value;
8912 else
8913 channel = 0;
8914 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
8915 req->ssid_len, req->bssid,
8916 bssid_hint, channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008917 if (0 > status) {
8918 hddLog(LOGE, FL("connect failed"));
8919 return status;
8920 }
8921 EXIT();
8922 return status;
8923}
8924
8925/**
8926 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
8927 * @wiphy: Pointer to wiphy
8928 * @dev: Pointer to network device
8929 * @req: Pointer to cfg80211 connect request
8930 *
8931 * Return: 0 for success, non-zero for failure
8932 */
8933static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8934 struct net_device *ndev,
8935 struct cfg80211_connect_params *req)
8936{
8937 int ret;
8938 cds_ssr_protect(__func__);
8939 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
8940 cds_ssr_unprotect(__func__);
8941
8942 return ret;
8943}
8944
8945/**
8946 * wlan_hdd_disconnect() - hdd disconnect api
8947 * @pAdapter: Pointer to adapter
8948 * @reason: Disconnect reason code
8949 *
8950 * This function is used to issue a disconnect request to SME
8951 *
8952 * Return: 0 for success, non-zero for failure
8953 */
8954int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
8955{
8956 int status, result = 0;
8957 unsigned long rc;
8958 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8959 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8960
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308961 ENTER();
8962
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008963 status = wlan_hdd_validate_context(pHddCtx);
8964
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308965 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008966 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008967
8968 /*stop tx queues */
8969 hddLog(LOG1, FL("Disabling queues"));
8970 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
8971 WLAN_CONTROL_PATH);
8972 hddLog(LOG1,
8973 FL("Set HDD connState to eConnectionState_Disconnecting"));
8974 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
8975 INIT_COMPLETION(pAdapter->disconnect_comp_var);
8976
8977 /*issue disconnect */
8978
8979 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8980 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +05308981 /*
8982 * Wait here instead of returning directly, this will block the next
8983 * connect command and allow processing of the scan for ssid and
8984 * the previous connect command in CSR. Else we might hit some
8985 * race conditions leading to SME and HDD out of sync.
8986 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308987 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308988 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008989 } else if (0 != status) {
8990 hddLog(LOGE,
8991 FL("csr_roam_disconnect failure, returned %d"),
8992 (int)status);
8993 pHddStaCtx->staDebugState = status;
8994 result = -EINVAL;
8995 goto disconnected;
8996 }
8997 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
8998 msecs_to_jiffies
8999 (WLAN_WAIT_TIME_DISCONNECT));
9000
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309001 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009002 hddLog(LOGE,
9003 FL("Failed to disconnect, timed out"));
9004 result = -ETIMEDOUT;
9005 }
9006disconnected:
9007 hddLog(LOG1,
9008 FL("Set HDD connState to eConnectionState_NotConnected"));
9009 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
9010#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
9011 /* Sending disconnect event to userspace for kernel version < 3.11
9012 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
9013 */
9014 hddLog(LOG1, FL("Send disconnected event to userspace"));
Ryan Hsua335c162016-01-21 12:12:20 -08009015 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, NULL, 0,
9016#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
9017 false,
9018#endif
9019 GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009020#endif
9021
9022 return result;
9023}
9024
9025/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009026 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
9027 * @reason: ieee80211 reason code.
9028 *
9029 * This utility function helps log string conversion of reason code.
9030 *
9031 * Return: string conversion of reason code, if match found;
9032 * "Unknown" otherwise.
9033 */
9034static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
9035{
9036 switch (reason) {
9037 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
9038 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
9039 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
9040 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
9041 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
9042 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
9043 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
9044 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
9045 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
9046 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
9047 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
9048 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
9049 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
9050 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
9051 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
9052 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
9053 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
9054 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
9055 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
9056 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
9057 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
9058 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
9059 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
9060 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
9061 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
9062 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
9063 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
9064 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
9065 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
9066 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
9067 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
9068 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
9069 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
9070 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
9071 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
9072 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
9073 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
9074 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
9075 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
9076 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
9077 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
9078 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
9079 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
9080 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
9081 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
9082 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
9083 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
9084 default:
9085 return "Unknown";
9086 }
9087}
9088
9089/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009090 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9091 * @wiphy: Pointer to wiphy
9092 * @dev: Pointer to network device
9093 * @reason: Disconnect reason code
9094 *
9095 * This function is used to issue a disconnect request to SME
9096 *
9097 * Return: 0 for success, non-zero for failure
9098 */
9099static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9100 struct net_device *dev, u16 reason)
9101{
9102 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9103 int status;
9104 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9105 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9106#ifdef FEATURE_WLAN_TDLS
9107 uint8_t staIdx;
9108#endif
9109
9110 ENTER();
9111
Anurag Chouhan6d760662016-02-20 16:05:43 +05309112 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9114 return -EINVAL;
9115 }
9116
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309117 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009118 TRACE_CODE_HDD_CFG80211_DISCONNECT,
9119 pAdapter->sessionId, reason));
9120 hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"),
9121 hdd_device_mode_to_string(pAdapter->device_mode),
9122 pAdapter->device_mode, reason);
9123
9124 status = wlan_hdd_validate_context(pHddCtx);
9125
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309126 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009127 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009128
9129 /* Issue disconnect request to SME, if station is in connected state */
9130 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
9131 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
9132 eCsrRoamDisconnectReason reasonCode =
9133 eCSR_DISCONNECT_REASON_UNSPECIFIED;
9134 hdd_scaninfo_t *pScanInfo;
9135
9136 switch (reason) {
9137 case WLAN_REASON_MIC_FAILURE:
9138 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
9139 break;
9140
9141 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
9142 case WLAN_REASON_DISASSOC_AP_BUSY:
9143 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
9144 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
9145 break;
9146
9147 case WLAN_REASON_PREV_AUTH_NOT_VALID:
9148 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
9149 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
9150 break;
9151
9152 case WLAN_REASON_DEAUTH_LEAVING:
9153 reasonCode =
9154 pHddCtx->config->
9155 gEnableDeauthToDisassocMap ?
9156 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
9157 eCSR_DISCONNECT_REASON_DEAUTH;
9158 break;
9159 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
9160 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
9161 break;
9162 default:
9163 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
9164 break;
9165 }
9166 hddLog(LOG1,
9167 FL("convert to internal reason %d to reasonCode %d"),
9168 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009169 pScanInfo = &pAdapter->scan_info;
9170 if (pScanInfo->mScanPending) {
9171 hddLog(LOG1,
9172 FL("Disconnect is in progress, Aborting Scan"));
9173 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
9174 eCSR_SCAN_ABORT_DEFAULT);
9175 }
9176#ifdef FEATURE_WLAN_TDLS
9177 /* First clean up the tdls peers if any */
9178 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
9179 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
9180 pAdapter->sessionId)
9181 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
9182 uint8_t *mac;
9183 mac =
9184 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
9185 hddLog(LOG1,
9186 "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d "
9187 MAC_ADDRESS_STR, __func__,
9188 pHddCtx->tdlsConnInfo[staIdx].staId,
9189 pAdapter->sessionId,
9190 MAC_ADDR_ARRAY(mac));
9191 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
9192 (pAdapter),
9193 pAdapter->sessionId, mac);
9194 }
9195 }
9196#endif
9197 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"),
9198 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009199 hdd_info("Disconnect request from user space with reason: %s",
9200 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009201 status = wlan_hdd_disconnect(pAdapter, reasonCode);
9202 if (0 != status) {
9203 hddLog(LOGE,
9204 FL("failure, returned %d"), status);
9205 return -EINVAL;
9206 }
9207 } else {
9208 hddLog(LOGE,
9209 FL("unexpected cfg disconnect called while in state (%d)"),
9210 pHddStaCtx->conn_info.connState);
9211 }
9212
9213 return status;
9214}
9215
9216/**
9217 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9218 * @wiphy: Pointer to wiphy
9219 * @dev: Pointer to network device
9220 * @reason: Disconnect reason code
9221 *
9222 * Return: 0 for success, non-zero for failure
9223 */
9224static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9225 struct net_device *dev, u16 reason)
9226{
9227 int ret;
9228 cds_ssr_protect(__func__);
9229 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
9230 cds_ssr_unprotect(__func__);
9231
9232 return ret;
9233}
9234
9235/**
9236 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
9237 * @pAdapter: Pointer to adapter
9238 * @param: Pointer to IBSS parameters
9239 *
9240 * This function is used to initialize the security settings in IBSS mode
9241 *
9242 * Return: 0 for success, non-zero for failure
9243 */
9244static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
9245 struct cfg80211_ibss_params
9246 *params)
9247{
9248 int status = 0;
9249 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9250 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9251 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9252
9253 ENTER();
9254
9255 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309256 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009257 pHddStaCtx->ibss_enc_key_installed = 0;
9258
9259 if (params->ie_len && (NULL != params->ie)) {
9260 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9261 params->ie_len, WLAN_EID_RSN)) {
9262 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9263 encryptionType = eCSR_ENCRYPT_TYPE_AES;
9264 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
9265 tDot11fIEWPA dot11WPAIE;
9266 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9267 u8 *ie;
9268
9269 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
9270 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9271 params->ie_len,
9272 DOT11F_EID_WPA);
9273 if (NULL != ie) {
9274 pWextState->wpaVersion =
9275 IW_AUTH_WPA_VERSION_WPA;
9276 /* Unpack the WPA IE */
9277 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
9278 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
9279 &ie[2 + 4],
9280 ie[1] - 4, &dot11WPAIE);
9281 /*Extract the multicast cipher, the encType for unicast
9282 cipher for wpa-none is none */
9283 encryptionType =
9284 hdd_translate_wpa_to_csr_encryption_type
9285 (dot11WPAIE.multicast_cipher);
9286 }
9287 }
9288
9289 status =
9290 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
9291 params->ie_len);
9292
9293 if (0 > status) {
9294 hddLog(LOGE, FL("failed to parse WPA/RSN IE"));
9295 return status;
9296 }
9297 }
9298
9299 pWextState->roamProfile.AuthType.authType[0] =
9300 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
9301
9302 if (params->privacy) {
9303 /* Security enabled IBSS, At this time there is no information
9304 * available about the security paramters, so initialise the
9305 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
9306 * The correct security parameters will be updated later in
9307 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
9308 * set inorder enable privacy bit in beacons
9309 */
9310
9311 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9312 }
9313 hddLog(LOG2, FL("encryptionType=%d"), encryptionType);
9314 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
9315 pWextState->roamProfile.EncryptionType.numEntries = 1;
9316 pWextState->roamProfile.EncryptionType.encryptionType[0] =
9317 encryptionType;
9318 return status;
9319}
9320
9321/**
9322 * __wlan_hdd_cfg80211_join_ibss() - join ibss
9323 * @wiphy: Pointer to wiphy
9324 * @dev: Pointer to network device
9325 * @param: Pointer to IBSS join parameters
9326 *
9327 * This function is used to create/join an IBSS network
9328 *
9329 * Return: 0 for success, non-zero for failure
9330 */
9331static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9332 struct net_device *dev,
9333 struct cfg80211_ibss_params *params)
9334{
9335 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9336 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9337 tCsrRoamProfile *pRoamProfile;
9338 int status;
9339 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9340 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +05309341 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009343
9344 ENTER();
9345
Anurag Chouhan6d760662016-02-20 16:05:43 +05309346 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9348 return -EINVAL;
9349 }
9350
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309351 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009352 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
9353 pAdapter->sessionId, pAdapter->device_mode));
9354 hddLog(LOG1, FL("Device_mode %s(%d)"),
9355 hdd_device_mode_to_string(pAdapter->device_mode),
9356 pAdapter->device_mode);
9357
9358 status = wlan_hdd_validate_context(pHddCtx);
9359
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309360 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009362
9363 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05309364 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009365 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9366 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9367 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9368 int indx;
9369
9370 /* Get channel number */
9371 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009372 params->
9373 chandef.
9374 chan->
9375 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009376
9377 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9378 validChan, &numChans)) {
9379 hddLog(LOGE, FL("No valid channel list"));
9380 return -EOPNOTSUPP;
9381 }
9382
9383 for (indx = 0; indx < numChans; indx++) {
9384 if (channelNum == validChan[indx]) {
9385 break;
9386 }
9387 }
9388 if (indx >= numChans) {
9389 hddLog(LOGE,
9390 FL("Not valid Channel %d"), channelNum);
9391 return -EINVAL;
9392 }
9393 }
9394
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009395 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009396 HW_MODE_20_MHZ)) {
9397 hdd_err("This concurrency combination is not allowed");
9398 return -ECONNREFUSED;
9399 }
9400 if (pHddCtx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309401 status = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309402 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009403 hdd_err("ERR: clear event failed");
9404
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05309405 status = cds_current_connections_update(pAdapter->sessionId,
9406 channelNum,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05309407 SIR_UPDATE_REASON_JOIN_IBSS);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309408 if (QDF_STATUS_E_FAILURE == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009409 hdd_err("ERROR: connections update failed!!");
9410 return -EINVAL;
9411 }
9412
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309413 if (QDF_STATUS_SUCCESS == status) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309414 status = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309415 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309416 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 return -EINVAL;
9418 }
9419 }
9420 }
9421
9422 /*Try disconnecting if already in connected state */
9423 status = wlan_hdd_try_disconnect(pAdapter);
9424 if (0 > status) {
9425 hddLog(LOGE,
9426 FL("Failed to disconnect the existing IBSS connection"));
9427 return -EALREADY;
9428 }
9429
9430 pRoamProfile = &pWextState->roamProfile;
9431
9432 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
9433 hddLog(LOGE,
9434 FL("Interface type is not set to IBSS"));
9435 return -EINVAL;
9436 }
9437
9438 /* enable selected protection checks in IBSS mode */
9439 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
9440
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309441 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009442 WNI_CFG_IBSS_ATIM_WIN_SIZE,
9443 pHddCtx->config->
9444 ibssATIMWinSize)) {
9445 hddLog(LOGE,
9446 FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"));
9447 }
9448
9449 /* BSSID is provided by upper layers hence no need to AUTO generate */
9450 if (NULL != params->bssid) {
9451 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309452 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009453 hddLog(LOGE,
9454 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
9455 return -EIO;
9456 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309457 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009458 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
9459 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309460 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009461 hddLog(LOGE,
9462 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
9463 return -EIO;
9464 }
Anurag Chouhanc5548422016-02-24 18:33:27 +05309465 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009466 }
9467 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
9468 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
9469 pRoamProfile->beaconInterval = params->beacon_interval;
9470 else {
9471 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
9472 hddLog(LOG2,
9473 FL("input beacon interval %d TU is invalid, use default %d TU"),
9474 params->beacon_interval, pRoamProfile->beaconInterval);
9475 }
9476
9477 /* Set Channel */
9478 if (channelNum) {
9479 /* Set the Operational Channel */
9480 hddLog(LOG2, FL("set channel %d"), channelNum);
9481 pRoamProfile->ChannelInfo.numOfChannels = 1;
9482 pHddStaCtx->conn_info.operationChannel = channelNum;
9483 pRoamProfile->ChannelInfo.ChannelList =
9484 &pHddStaCtx->conn_info.operationChannel;
9485 }
9486
9487 /* Initialize security parameters */
9488 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
9489 if (status < 0) {
9490 hddLog(LOGE,
9491 FL("failed to set security parameters"));
9492 return status;
9493 }
9494
9495 /* Issue connect start */
9496 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
9497 params->ssid_len,
9498 bssid.bytes,
9499 NULL,
9500 pHddStaCtx->conn_info.
9501 operationChannel);
9502
9503 if (0 > status) {
9504 hddLog(LOGE, FL("connect failed"));
9505 return status;
9506 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309507 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009508 return 0;
9509}
9510
9511/**
9512 * wlan_hdd_cfg80211_join_ibss() - join ibss
9513 * @wiphy: Pointer to wiphy
9514 * @dev: Pointer to network device
9515 * @param: Pointer to IBSS join parameters
9516 *
9517 * This function is used to create/join an IBSS network
9518 *
9519 * Return: 0 for success, non-zero for failure
9520 */
9521static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9522 struct net_device *dev,
9523 struct cfg80211_ibss_params *params)
9524{
9525 int ret = 0;
9526
9527 cds_ssr_protect(__func__);
9528 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
9529 cds_ssr_unprotect(__func__);
9530
9531 return ret;
9532}
9533
9534/**
9535 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
9536 * @wiphy: Pointer to wiphy
9537 * @dev: Pointer to network device
9538 *
9539 * This function is used to leave an IBSS network
9540 *
9541 * Return: 0 for success, non-zero for failure
9542 */
9543static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9544 struct net_device *dev)
9545{
9546 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9547 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9548 tCsrRoamProfile *pRoamProfile;
9549 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9550 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309551 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +05309552 unsigned long rc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553
9554 ENTER();
9555
Anurag Chouhan6d760662016-02-20 16:05:43 +05309556 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009557 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9558 return -EINVAL;
9559 }
9560
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309561 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009562 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
9563 pAdapter->sessionId,
9564 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
9565 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309566 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009568
9569 hddLog(LOG1, FL("Device_mode %s(%d)"),
9570 hdd_device_mode_to_string(pAdapter->device_mode),
9571 pAdapter->device_mode);
9572 if (NULL == pWextState) {
9573 hddLog(LOGE, FL("Data Storage Corruption"));
9574 return -EIO;
9575 }
9576
9577 pRoamProfile = &pWextState->roamProfile;
9578
9579 /* Issue disconnect only if interface type is set to IBSS */
9580 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
9581 hddLog(LOGE,
9582 FL("BSS Type is not set to IBSS"));
9583 return -EINVAL;
9584 }
9585
9586 /* Issue Disconnect request */
9587 INIT_COMPLETION(pAdapter->disconnect_comp_var);
9588 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9589 pAdapter->sessionId,
9590 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309591 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009592 hddLog(LOGE,
9593 FL("sme_roam_disconnect failed hal_status(%d)"),
9594 hal_status);
9595 return -EAGAIN;
9596 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +05309597
9598 /* wait for mc thread to cleanup and then return to upper stack
9599 * so by the time upper layer calls the change interface, we are
9600 * all set to proceed further
9601 */
9602 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
9603 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9604 if (!rc) {
9605 hdd_err("Failed to disconnect, timed out");
9606 return -ETIMEDOUT;
9607 }
9608
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309609 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 return 0;
9611}
9612
9613/**
9614 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
9615 * @wiphy: Pointer to wiphy
9616 * @dev: Pointer to network device
9617 *
9618 * This function is used to leave an IBSS network
9619 *
9620 * Return: 0 for success, non-zero for failure
9621 */
9622static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9623 struct net_device *dev)
9624{
9625 int ret = 0;
9626
9627 cds_ssr_protect(__func__);
9628 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
9629 cds_ssr_unprotect(__func__);
9630
9631 return ret;
9632}
9633
9634/**
9635 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9636 * @wiphy: Pointer to wiphy
9637 * @changed: Parameters changed
9638 *
9639 * This function is used to set the phy parameters. RTS Threshold/FRAG
9640 * Threshold/Retry Count etc.
9641 *
9642 * Return: 0 for success, non-zero for failure
9643 */
9644static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
9645 u32 changed)
9646{
9647 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9648 tHalHandle hHal = pHddCtx->hHal;
9649 int status;
9650
9651 ENTER();
9652
Anurag Chouhan6d760662016-02-20 16:05:43 +05309653 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009654 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9655 return -EINVAL;
9656 }
9657
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309658 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009659 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
9660 NO_SESSION, wiphy->rts_threshold));
9661 status = wlan_hdd_validate_context(pHddCtx);
9662
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309663 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009664 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009665
9666 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
9667 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
9668 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
9669
9670 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
9671 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
9672 hddLog(LOGE,
9673 FL("Invalid RTS Threshold value %u"),
9674 rts_threshold);
9675 return -EINVAL;
9676 }
9677
9678 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
9679 rts_threshold)) {
9680 hddLog(LOGE,
9681 FL("sme_cfg_set_int failed for rts_threshold value %u"),
9682 rts_threshold);
9683 return -EIO;
9684 }
9685
9686 hddLog(LOG2, FL("set rts threshold %u"), rts_threshold);
9687 }
9688
9689 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
9690 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
9691 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
9692 wiphy->frag_threshold;
9693
9694 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
9695 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
9696 hddLog(LOGE,
9697 FL("Invalid frag_threshold value %hu"),
9698 frag_threshold);
9699 return -EINVAL;
9700 }
9701
9702 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
9703 frag_threshold)) {
9704 hddLog(LOGE,
9705 FL("sme_cfg_set_int failed for frag_threshold value %hu"),
9706 frag_threshold);
9707 return -EIO;
9708 }
9709
9710 hddLog(LOG2, FL("set frag threshold %hu"), frag_threshold);
9711 }
9712
9713 if ((changed & WIPHY_PARAM_RETRY_SHORT)
9714 || (changed & WIPHY_PARAM_RETRY_LONG)) {
9715 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
9716 wiphy->retry_short : wiphy->retry_long;
9717
9718 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
9719 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
9720 hddLog(LOGE,
9721 FL("Invalid Retry count %hu"), retry_value);
9722 return -EINVAL;
9723 }
9724
9725 if (changed & WIPHY_PARAM_RETRY_SHORT) {
9726 if (0 != sme_cfg_set_int(hHal,
9727 WNI_CFG_LONG_RETRY_LIMIT,
9728 retry_value)) {
9729 hddLog(LOGE,
9730 FL("sme_cfg_set_int failed for long retry count %hu"),
9731 retry_value);
9732 return -EIO;
9733 }
9734 hddLog(LOG2,
9735 FL("set long retry count %hu"), retry_value);
9736 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
9737 if (0 != sme_cfg_set_int(hHal,
9738 WNI_CFG_SHORT_RETRY_LIMIT,
9739 retry_value)) {
9740 hddLog(LOGE,
9741 FL("sme_cfg_set_int failed for short retry count %hu"),
9742 retry_value);
9743 return -EIO;
9744 }
9745 hddLog(LOG2,
9746 FL("set short retry count %hu"), retry_value);
9747 }
9748 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309749 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009750 return 0;
9751}
9752
9753/**
9754 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9755 * @wiphy: Pointer to wiphy
9756 * @changed: Parameters changed
9757 *
9758 * Return: 0 for success, non-zero for failure
9759 */
9760static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
9761{
9762 int ret;
9763
9764 cds_ssr_protect(__func__);
9765 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
9766 cds_ssr_unprotect(__func__);
9767
9768 return ret;
9769}
9770
9771/**
9772 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
9773 * key
9774 * @wiphy: Pointer to wiphy
9775 * @dev: Pointer to network device
9776 * @key_index: Key index
9777 *
9778 * Return: 0
9779 */
9780static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9781 struct net_device *netdev,
9782 u8 key_index)
9783{
9784 ENTER();
9785 return 0;
9786}
9787
9788/**
9789 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
9790 * wlan_hdd_set_default_mgmt_key
9791 * @wiphy: pointer to wiphy
9792 * @netdev: pointer to net_device structure
9793 * @key_index: key index
9794 *
9795 * Return: 0 on success, error number on failure
9796 */
9797static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9798 struct net_device *netdev,
9799 u8 key_index)
9800{
9801 int ret;
9802
9803 cds_ssr_protect(__func__);
9804 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
9805 cds_ssr_unprotect(__func__);
9806
9807 return ret;
9808}
9809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810/**
9811 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
9812 * @wiphy: Pointer to wiphy
9813 * @dev: Pointer to network device
9814 * @params: Pointer to tx queue parameters
9815 *
9816 * Return: 0
9817 */
9818static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
9819 struct net_device *dev,
9820 struct ieee80211_txq_params *params)
9821{
9822 ENTER();
9823 return 0;
9824}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009825
9826/**
9827 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
9828 * @wiphy: pointer to wiphy
9829 * @netdev: pointer to net_device structure
9830 * @params: pointer to ieee80211_txq_params
9831 *
9832 * Return: 0 on success, error number on failure
9833 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
9835 struct net_device *dev,
9836 struct ieee80211_txq_params *params)
9837{
9838 int ret;
9839
9840 cds_ssr_protect(__func__);
9841 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
9842 cds_ssr_unprotect(__func__);
9843
9844 return ret;
9845}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009846
9847/**
9848 * __wlan_hdd_cfg80211_del_station() - delete station v2
9849 * @wiphy: Pointer to wiphy
9850 * @param: Pointer to delete station parameter
9851 *
9852 * Return: 0 for success, non-zero for failure
9853 */
9854static
9855int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9856 struct net_device *dev,
9857 struct tagCsrDelStaParams *pDelStaParams)
9858{
9859 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9860 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309861 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009862 hdd_hostapd_state_t *hapd_state;
9863 int status;
9864 uint8_t staId;
9865 uint8_t *mac;
9866
9867 ENTER();
9868
Anurag Chouhan6d760662016-02-20 16:05:43 +05309869 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9871 return -EINVAL;
9872 }
9873
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309874 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875 TRACE_CODE_HDD_CFG80211_DEL_STA,
9876 pAdapter->sessionId, pAdapter->device_mode));
9877
9878 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9879 status = wlan_hdd_validate_context(pHddCtx);
9880
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309881 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009883
9884 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
9885
9886 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
9887 (WLAN_HDD_P2P_GO == pAdapter->device_mode)) {
9888
9889 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9890 if (!hapd_state) {
9891 hddLog(LOGE, "%s: Hostapd State is Null", __func__);
9892 return 0;
9893 }
9894
Anurag Chouhanc5548422016-02-24 18:33:27 +05309895 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009896 uint16_t i;
9897 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
9898 if ((pAdapter->aStaInfo[i].isUsed) &&
9899 (!pAdapter->aStaInfo[i].
9900 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309901 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009902 mac,
9903 pAdapter->aStaInfo[i].
9904 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309905 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009906 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
9907 hdd_ipa_wlan_evt(pAdapter,
9908 pAdapter->
9909 aStaInfo[i].
9910 ucSTAId,
9911 WLAN_CLIENT_DISCONNECT,
9912 mac);
9913 }
9914 hddLog(LOG1,
9915 FL("Delete STA with MAC::"
9916 MAC_ADDRESS_STR),
9917 MAC_ADDR_ARRAY(mac));
9918
9919 if (pHddCtx->dev_dfs_cac_status ==
9920 DFS_CAC_IN_PROGRESS)
9921 goto fn_end;
9922
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309923 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009924 hdd_softap_sta_disassoc(pAdapter,
9925 mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309926 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009927 hdd_softap_sta_deauth(pAdapter,
9928 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309929 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930 pAdapter->aStaInfo[i].
9931 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309932 qdf_status =
9933 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309934 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009935 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +05309936 if (!QDF_IS_STATUS_SUCCESS(
9937 qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009938 hddLog(LOGE,
9939 "%s: Deauth wait time expired",
9940 __func__);
9941 }
9942 }
9943 }
9944 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309945 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009946 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309947 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009948 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309949 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009950 hddLog(LOG1,
9951 FL("Skip DEL STA as this is not used::"
9952 MAC_ADDRESS_STR),
9953 MAC_ADDR_ARRAY(mac));
9954 return -ENOENT;
9955 }
9956
9957 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
9958 hdd_ipa_wlan_evt(pAdapter, staId,
9959 WLAN_CLIENT_DISCONNECT, mac);
9960 }
9961
9962 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
9963 true) {
9964 hddLog(LOG1,
9965 FL("Skip DEL STA as deauth is in progress::"
9966 MAC_ADDRESS_STR),
9967 MAC_ADDR_ARRAY(mac));
9968 return -ENOENT;
9969 }
9970
9971 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
9972
9973 hddLog(LOG1,
9974 FL("Delete STA with MAC::" MAC_ADDRESS_STR),
9975 MAC_ADDR_ARRAY(mac));
9976
9977 /* Case: SAP in ACS selected DFS ch and client connected
9978 * Now Radar detected. Then if random channel is another
9979 * DFS ch then new CAC is initiated and no TX allowed.
9980 * So do not send any mgmt frames as it will timeout
9981 * during CAC.
9982 */
9983
9984 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
9985 goto fn_end;
9986
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309987 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009988 hdd_softap_sta_disassoc(pAdapter, mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309989 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309991 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 pAdapter->aStaInfo[staId].isDeauthInProgress =
9993 false;
9994 hddLog(LOG1,
9995 FL("STA removal failed for ::"
9996 MAC_ADDRESS_STR),
9997 MAC_ADDR_ARRAY(mac));
9998 return -ENOENT;
9999 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010000 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010001 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010002 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010003 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004 hddLog(LOGE,
10005 "%s: Deauth wait time expired",
10006 __func__);
10007 }
10008 }
10009 }
10010
10011fn_end:
10012 EXIT();
10013 return 0;
10014}
10015
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010016#if defined(USE_CFG80211_DEL_STA_V2)
10017/**
10018 * wlan_hdd_del_station() - delete station wrapper
10019 * @adapter: pointer to the hdd adapter
10020 *
10021 * Return: None
10022 */
10023void wlan_hdd_del_station(hdd_adapter_t *adapter)
10024{
10025 struct station_del_parameters del_sta;
10026 del_sta.mac = NULL;
10027 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10028 del_sta.reason_code = eCsrForcedDeauthSta;
10029
10030 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
10031 &del_sta);
10032}
10033#else
10034void wlan_hdd_del_station(hdd_adapter_t *adapter)
10035{
10036 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
10037}
10038#endif
10039
10040#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041/**
10042 * wlan_hdd_cfg80211_del_station() - delete station v2
10043 * @wiphy: Pointer to wiphy
10044 * @param: Pointer to delete station parameter
10045 *
10046 * Return: 0 for success, non-zero for failure
10047 */
10048int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10049 struct net_device *dev,
10050 struct station_del_parameters *param)
10051#else
10052/**
10053 * wlan_hdd_cfg80211_del_station() - delete station
10054 * @wiphy: Pointer to wiphy
10055 * @mac: Pointer to station mac address
10056 *
10057 * Return: 0 for success, non-zero for failure
10058 */
10059#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10060int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10061 struct net_device *dev,
10062 const uint8_t *mac)
10063#else
10064int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10065 struct net_device *dev,
10066 uint8_t *mac)
10067#endif
10068#endif
10069{
10070 int ret;
10071 struct tagCsrDelStaParams delStaParams;
10072
10073 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010074#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010075 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010076 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010077 return -EINVAL;
10078 }
10079 wlansap_populate_del_sta_params(param->mac, param->reason_code,
10080 param->subtype, &delStaParams);
10081#else
10082 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
10083 (SIR_MAC_MGMT_DEAUTH >> 4),
10084 &delStaParams);
10085#endif
10086 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
10087 cds_ssr_unprotect(__func__);
10088
10089 return ret;
10090}
10091
10092/**
10093 * __wlan_hdd_cfg80211_add_station() - add station
10094 * @wiphy: Pointer to wiphy
10095 * @mac: Pointer to station mac address
10096 * @pmksa: Pointer to add station parameter
10097 *
10098 * Return: 0 for success, non-zero for failure
10099 */
10100static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10101 struct net_device *dev,
10102 const uint8_t *mac,
10103 struct station_parameters *params)
10104{
10105 int status = -EPERM;
10106#ifdef FEATURE_WLAN_TDLS
10107 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10108 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10109 u32 mask, set;
10110
10111 ENTER();
10112
Anurag Chouhan6d760662016-02-20 16:05:43 +053010113 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10115 return -EINVAL;
10116 }
10117
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010118 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010119 TRACE_CODE_HDD_CFG80211_ADD_STA,
10120 pAdapter->sessionId, params->listen_interval));
10121
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010122 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010123 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124
10125 mask = params->sta_flags_mask;
10126
10127 set = params->sta_flags_set;
10128
10129 hddLog(LOG1, FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), mask, set,
10130 MAC_ADDR_ARRAY(mac));
10131
10132 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10133 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10134 status =
10135 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
10136 }
10137 }
10138#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010139 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140 return status;
10141}
10142
10143/**
10144 * wlan_hdd_cfg80211_add_station() - add station
10145 * @wiphy: Pointer to wiphy
10146 * @mac: Pointer to station mac address
10147 * @pmksa: Pointer to add station parameter
10148 *
10149 * Return: 0 for success, non-zero for failure
10150 */
10151#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10152static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10153 struct net_device *dev,
10154 const uint8_t *mac,
10155 struct station_parameters *params)
10156#else
10157static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10158 struct net_device *dev, uint8_t *mac,
10159 struct station_parameters *params)
10160#endif
10161{
10162 int ret;
10163
10164 cds_ssr_protect(__func__);
10165 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
10166 cds_ssr_unprotect(__func__);
10167
10168 return ret;
10169}
10170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171/**
10172 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
10173 * @wiphy: Pointer to wiphy
10174 * @dev: Pointer to network device
10175 * @pmksa: Pointer to set pmksa parameter
10176 *
10177 * Return: 0 for success, non-zero for failure
10178 */
10179static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10180 struct net_device *dev,
10181 struct cfg80211_pmksa *pmksa)
10182{
10183 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10184 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10185 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010186 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 int status;
10188 tPmkidCacheInfo pmk_id;
10189
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010190 ENTER();
10191
Anurag Chouhan6d760662016-02-20 16:05:43 +053010192 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10194 return -EINVAL;
10195 }
10196
10197 if (!pmksa) {
10198 hddLog(LOGE, FL("pmksa is NULL"));
10199 return -EINVAL;
10200 }
10201
10202 if (!pmksa->bssid || !pmksa->pmkid) {
10203 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
10204 pmksa->bssid, pmksa->pmkid);
10205 return -EINVAL;
10206 }
10207
10208 hddLog(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR),
10209 MAC_ADDR_ARRAY(pmksa->bssid));
10210
10211 status = wlan_hdd_validate_context(pHddCtx);
10212
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010213 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215
10216 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10217
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010218 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
10219 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010220
10221 /* Add to the PMKSA ID Cache in CSR */
10222 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
10223 &pmk_id, 1, false);
10224
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010225 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
10227 pAdapter->sessionId, result));
10228
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010229 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010230 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010231}
10232
10233/**
10234 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
10235 * @wiphy: Pointer to wiphy
10236 * @dev: Pointer to network device
10237 * @pmksa: Pointer to set pmksa parameter
10238 *
10239 * Return: 0 for success, non-zero for failure
10240 */
10241static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10242 struct net_device *dev,
10243 struct cfg80211_pmksa *pmksa)
10244{
10245 int ret;
10246
10247 cds_ssr_protect(__func__);
10248 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
10249 cds_ssr_unprotect(__func__);
10250
10251 return ret;
10252}
10253
10254/**
10255 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10256 * @wiphy: Pointer to wiphy
10257 * @dev: Pointer to network device
10258 * @pmksa: Pointer to pmksa parameter
10259 *
10260 * Return: 0 for success, non-zero for failure
10261 */
10262static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10263 struct net_device *dev,
10264 struct cfg80211_pmksa *pmksa)
10265{
10266 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10267 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10268 tHalHandle halHandle;
10269 int status = 0;
10270
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010271 ENTER();
10272
Anurag Chouhan6d760662016-02-20 16:05:43 +053010273 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010274 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10275 return -EINVAL;
10276 }
10277
10278 if (!pmksa) {
10279 hddLog(LOGE, FL("pmksa is NULL"));
10280 return -EINVAL;
10281 }
10282
10283 if (!pmksa->bssid) {
10284 hddLog(LOGE, FL("pmksa->bssid is NULL"));
10285 return -EINVAL;
10286 }
10287
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010288 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010289 MAC_ADDR_ARRAY(pmksa->bssid));
10290
10291 status = wlan_hdd_validate_context(pHddCtx);
10292
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010293 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010294 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010295
10296 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10297
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010298 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010299 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
10300 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010301 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010302 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010303 sme_roam_del_pmkid_from_cache(halHandle,
10304 pAdapter->sessionId, pmksa->bssid,
10305 false)) {
10306 hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR),
10307 MAC_ADDR_ARRAY(pmksa->bssid));
10308 status = -EINVAL;
10309 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010310 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 return status;
10312}
10313
10314/**
10315 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10316 * @wiphy: Pointer to wiphy
10317 * @dev: Pointer to network device
10318 * @pmksa: Pointer to pmksa parameter
10319 *
10320 * Return: 0 for success, non-zero for failure
10321 */
10322static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10323 struct net_device *dev,
10324 struct cfg80211_pmksa *pmksa)
10325{
10326 int ret;
10327
10328 cds_ssr_protect(__func__);
10329 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
10330 cds_ssr_unprotect(__func__);
10331
10332 return ret;
10333
10334}
10335
10336/**
10337 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10338 * @wiphy: Pointer to wiphy
10339 * @dev: Pointer to network device
10340 *
10341 * Return: 0 for success, non-zero for failure
10342 */
10343static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10344 struct net_device *dev)
10345{
10346 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10347 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10348 tHalHandle halHandle;
10349 int status = 0;
10350
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010351 ENTER();
10352
Anurag Chouhan6d760662016-02-20 16:05:43 +053010353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10355 return -EINVAL;
10356 }
10357
10358 hddLog(LOGW, FL("Flushing PMKSA"));
10359
10360 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10361 status = wlan_hdd_validate_context(pHddCtx);
10362
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010363 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010365
10366 /* Retrieve halHandle */
10367 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10368
10369 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010370 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010371 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
10372 true)) {
10373 hddLog(LOGE, FL("Cannot flush PMKIDCache"));
10374 status = -EINVAL;
10375 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010376 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010377 return status;
10378}
10379
10380/**
10381 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10382 * @wiphy: Pointer to wiphy
10383 * @dev: Pointer to network device
10384 *
10385 * Return: 0 for success, non-zero for failure
10386 */
10387static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10388 struct net_device *dev)
10389{
10390 int ret;
10391
10392 cds_ssr_protect(__func__);
10393 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
10394 cds_ssr_unprotect(__func__);
10395
10396 return ret;
10397}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010398
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080010399#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010400/**
10401 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
10402 * @wiphy: Pointer to wiphy
10403 * @dev: Pointer to network device
10404 * @ftie: Pointer to fast transition ie parameter
10405 *
10406 * Return: 0 for success, non-zero for failure
10407 */
10408static int
10409__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
10410 struct net_device *dev,
10411 struct cfg80211_update_ft_ies_params *ftie)
10412{
10413 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
10414 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10415 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10416 int status;
10417
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010418 ENTER();
10419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010420 status = wlan_hdd_validate_context(hdd_ctx);
10421 if (status)
10422 return status;
10423
Anurag Chouhan6d760662016-02-20 16:05:43 +053010424 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010425 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10426 return -EINVAL;
10427 }
10428
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010429 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010430 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
10431 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
10432 /* Added for debug on reception of Re-assoc Req. */
10433 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
10434 hddLog(LOGE,
10435 FL("Called with Ie of length = %zu when not associated"),
10436 ftie->ie_len);
10437 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
10438 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010439 hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__,
10440 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010441
10442 /* Pass the received FT IEs to SME */
10443 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
10444 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010445 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446 return 0;
10447}
10448
10449/**
10450 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
10451 * @wiphy: Pointer to wiphy
10452 * @dev: Pointer to network device
10453 * @ftie: Pointer to fast transition ie parameter
10454 *
10455 * Return: 0 for success, non-zero for failure
10456 */
10457static int
10458wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
10459 struct net_device *dev,
10460 struct cfg80211_update_ft_ies_params *ftie)
10461{
10462 int ret;
10463
10464 cds_ssr_protect(__func__);
10465 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
10466 cds_ssr_unprotect(__func__);
10467
10468 return ret;
10469}
10470#endif
10471
10472#ifdef WLAN_FEATURE_GTK_OFFLOAD
10473/**
10474 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
10475 * @callbackContext: Callback context
10476 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
10477 *
10478 * Callback rountine called upon receiving response for get offload info
10479 *
10480 * Return: none
10481 */
10482void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
10483 tpSirGtkOffloadGetInfoRspParams
10484 pGtkOffloadGetInfoRsp)
10485{
10486 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
10487 uint8_t tempReplayCounter[8];
10488 hdd_station_ctx_t *pHddStaCtx;
10489
10490 ENTER();
10491
10492 if (NULL == pAdapter) {
10493 hddLog(LOGE, FL("HDD adapter is Null"));
10494 return;
10495 }
10496
10497 if (NULL == pGtkOffloadGetInfoRsp) {
10498 hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null"));
10499 return;
10500 }
10501
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010502 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503 hddLog(LOGE, FL("wlan Failed to get replay counter value"));
10504 return;
10505 }
10506
10507 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10508 /* Update replay counter */
10509 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
10510 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
10511
10512 {
10513 /* changing from little to big endian since supplicant
10514 * works on big endian format
10515 */
10516 int i;
10517 uint8_t *p =
10518 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
10519
10520 for (i = 0; i < 8; i++) {
10521 tempReplayCounter[7 - i] = (uint8_t) p[i];
10522 }
10523 }
10524
10525 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080010526 cfg80211_gtk_rekey_notify(pAdapter->dev,
10527 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010528 tempReplayCounter, GFP_KERNEL);
10529}
10530
10531/**
10532 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10533 * @wiphy: Pointer to wiphy
10534 * @dev: Pointer to network device
10535 * @data: Pointer to rekey data
10536 *
10537 * This function is used to offload GTK rekeying job to the firmware.
10538 *
10539 * Return: 0 for success, non-zero for failure
10540 */
10541int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10542 struct net_device *dev,
10543 struct cfg80211_gtk_rekey_data *data)
10544{
10545 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10546 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10547 hdd_station_ctx_t *pHddStaCtx;
10548 tHalHandle hHal;
10549 int result;
10550 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010551 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552
10553 ENTER();
10554
Anurag Chouhan6d760662016-02-20 16:05:43 +053010555 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10557 return -EINVAL;
10558 }
10559
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010560 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
10562 pAdapter->sessionId, pAdapter->device_mode));
10563
10564 result = wlan_hdd_validate_context(pHddCtx);
10565
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010566 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010568
10569 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10570 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10571 if (NULL == hHal) {
10572 hddLog(LOGE, FL("HAL context is Null!!!"));
10573 return -EAGAIN;
10574 }
10575
10576 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
10577 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
10578 NL80211_KCK_LEN);
10579 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
10580 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053010581 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080010582 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010583 {
10584 /* changing from big to little endian since driver
10585 * works on little endian format
10586 */
10587 uint8_t *p =
10588 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
10589 ullKeyReplayCounter;
10590 int i;
10591
10592 for (i = 0; i < 8; i++) {
10593 p[7 - i] = data->replay_ctr[i];
10594 }
10595 }
10596
10597 if (true == pHddCtx->hdd_wlan_suspended) {
10598 /* if wlan is suspended, enable GTK offload directly from here */
10599 memcpy(&hddGtkOffloadReqParams,
10600 &pHddStaCtx->gtkOffloadReqParams,
10601 sizeof(tSirGtkOffloadParams));
10602 status =
10603 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
10604 pAdapter->sessionId);
10605
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010606 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"),
10608 status);
10609 return -EINVAL;
10610 }
10611 hddLog(LOG1, FL("sme_set_gtk_offload successful"));
10612 } else {
10613 hddLog(LOG1,
10614 FL("wlan not suspended GTKOffload request is stored"));
10615 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010616 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010617 return result;
10618}
10619
10620/**
10621 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10622 * @wiphy: Pointer to wiphy
10623 * @dev: Pointer to network device
10624 * @data: Pointer to rekey data
10625 *
10626 * This function is used to offload GTK rekeying job to the firmware.
10627 *
10628 * Return: 0 for success, non-zero for failure
10629 */
10630int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10631 struct net_device *dev,
10632 struct cfg80211_gtk_rekey_data *data)
10633{
10634 int ret;
10635
10636 cds_ssr_protect(__func__);
10637 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
10638 cds_ssr_unprotect(__func__);
10639
10640 return ret;
10641}
10642#endif /*WLAN_FEATURE_GTK_OFFLOAD */
10643
10644/**
10645 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
10646 * @wiphy: Pointer to wiphy
10647 * @dev: Pointer to network device
10648 * @param: Pointer to access control parameter
10649 *
10650 * Return: 0 for success, non-zero for failure
10651 */
10652static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10653 struct net_device *dev,
10654 const struct cfg80211_acl_data *params)
10655{
10656 int i;
10657 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10658 hdd_hostapd_state_t *pHostapdState;
10659 tsap_Config_t *pConfig;
10660 v_CONTEXT_t p_cds_context = NULL;
10661 hdd_context_t *pHddCtx;
10662 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010663 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664
10665 ENTER();
10666
Anurag Chouhan6d760662016-02-20 16:05:43 +053010667 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010668 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10669 return -EINVAL;
10670 }
10671
10672 if (NULL == params) {
10673 hddLog(LOGE, FL("params is Null"));
10674 return -EINVAL;
10675 }
10676
10677 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10678 status = wlan_hdd_validate_context(pHddCtx);
10679
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010680 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010681 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010682
10683 p_cds_context = pHddCtx->pcds_context;
10684 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10685
10686 if (NULL == pHostapdState) {
10687 hddLog(LOGE, FL("pHostapdState is Null"));
10688 return -EINVAL;
10689 }
10690
10691 hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy,
10692 params->n_acl_entries);
10693
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010694 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010695 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
10696 pAdapter->sessionId, pAdapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 if (WLAN_HDD_SOFTAP == pAdapter->device_mode) {
10698 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
10699
10700 /* default value */
10701 pConfig->num_accept_mac = 0;
10702 pConfig->num_deny_mac = 0;
10703
10704 /**
10705 * access control policy
10706 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
10707 * listed in hostapd.deny file.
10708 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
10709 * listed in hostapd.accept file.
10710 */
10711 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
10712 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
10713 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
10714 params->acl_policy) {
10715 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
10716 } else {
10717 hddLog(LOGE, FL("Acl Policy : %d is not supported"),
10718 params->acl_policy);
10719 return -ENOTSUPP;
10720 }
10721
10722 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
10723 pConfig->num_accept_mac = params->n_acl_entries;
10724 for (i = 0; i < params->n_acl_entries; i++) {
10725 hddLog(LOG1,
10726 FL("** Add ACL MAC entry %i in WhiletList :"
10727 MAC_ADDRESS_STR), i,
10728 MAC_ADDR_ARRAY(
10729 params->mac_addrs[i].addr));
10730
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010731 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010732 params->mac_addrs[i].addr,
10733 sizeof(qcmacaddr));
10734 }
10735 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
10736 pConfig->num_deny_mac = params->n_acl_entries;
10737 for (i = 0; i < params->n_acl_entries; i++) {
10738 hddLog(LOG1,
10739 FL("** Add ACL MAC entry %i in BlackList :"
10740 MAC_ADDRESS_STR), i,
10741 MAC_ADDR_ARRAY(
10742 params->mac_addrs[i].addr));
10743
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010744 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010745 params->mac_addrs[i].addr,
10746 sizeof(qcmacaddr));
10747 }
10748 }
10749#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010750 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751 wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
10752 pConfig);
10753#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010754 qdf_status = wlansap_set_mac_acl(p_cds_context, pConfig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010756 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 hddLog(LOGE, FL("SAP Set Mac Acl fail"));
10758 return -EINVAL;
10759 }
10760 } else {
10761 hddLog(LOG1, FL("Invalid device_mode %s(%d)"),
10762 hdd_device_mode_to_string(pAdapter->device_mode),
10763 pAdapter->device_mode);
10764 return -EINVAL;
10765 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010766 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767 return 0;
10768}
10769
10770/**
10771 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
10772 * __wlan_hdd_cfg80211_set_mac_acl
10773 * @wiphy: pointer to wiphy structure
10774 * @dev: pointer to net_device
10775 * @params: pointer to cfg80211_acl_data
10776 *
10777 * Return; 0 on success, error number otherwise
10778 */
10779static int
10780wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10781 struct net_device *dev,
10782 const struct cfg80211_acl_data *params)
10783{
10784 int ret;
10785
10786 cds_ssr_protect(__func__);
10787 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
10788 cds_ssr_unprotect(__func__);
10789
10790 return ret;
10791}
10792
10793#ifdef WLAN_NL80211_TESTMODE
10794#ifdef FEATURE_WLAN_LPHB
10795/**
10796 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
10797 * @pHddCtx: Pointer to hdd context
10798 * @lphbInd: Pointer to low power heart beat indication parameter
10799 *
10800 * Return: none
10801 */
10802void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
10803{
10804 struct sk_buff *skb;
10805
10806 hddLog(LOGE, FL("LPHB indication arrived"));
10807
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010808 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010809 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810
10811 if (NULL == lphbInd) {
10812 hddLog(LOGE, FL("invalid argument lphbInd"));
10813 return;
10814 }
10815
10816 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
10817 wiphy, sizeof(tSirLPHBInd),
10818 GFP_ATOMIC);
10819 if (!skb) {
10820 hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail"));
10821 return;
10822 }
10823
10824 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
10825 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail"));
10826 goto nla_put_failure;
10827 }
10828 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
10829 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail"));
10830 goto nla_put_failure;
10831 }
10832 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
10833 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail"));
10834 goto nla_put_failure;
10835 }
10836 cfg80211_testmode_event(skb, GFP_ATOMIC);
10837 return;
10838
10839nla_put_failure:
10840 hddLog(LOGE, FL("NLA Put fail"));
10841 kfree_skb(skb);
10842
10843 return;
10844}
10845#endif /* FEATURE_WLAN_LPHB */
10846
10847/**
10848 * __wlan_hdd_cfg80211_testmode() - test mode
10849 * @wiphy: Pointer to wiphy
10850 * @data: Data pointer
10851 * @len: Data length
10852 *
10853 * Return: 0 for success, non-zero for failure
10854 */
10855static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10856 void *data, int len)
10857{
10858 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
10859 int err;
10860 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10861
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010862 ENTER();
10863
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 err = wlan_hdd_validate_context(pHddCtx);
10865 if (err)
10866 return err;
10867
10868 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
10869 len, wlan_hdd_tm_policy);
10870 if (err) {
10871 hddLog(LOGE, FL("Testmode INV ATTR"));
10872 return err;
10873 }
10874
10875 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
10876 hddLog(LOGE, FL("Testmode INV CMD"));
10877 return -EINVAL;
10878 }
10879
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010880 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010881 TRACE_CODE_HDD_CFG80211_TESTMODE,
10882 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010883 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
10884#ifdef FEATURE_WLAN_LPHB
10885 /* Low Power Heartbeat configuration request */
10886 case WLAN_HDD_TM_CMD_WLAN_HB:
10887 {
10888 int buf_len;
10889 void *buf;
10890 tSirLPHBReq *hb_params = NULL;
10891 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010892 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893
10894 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
10895 hddLog(LOGE, FL("Testmode INV DATA"));
10896 return -EINVAL;
10897 }
10898
10899 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
10900 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
10901
10902 hb_params_temp = (tSirLPHBReq *) buf;
10903 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
10904 && (hb_params_temp->params.lphbTcpParamReq.
10905 timePeriodSec == 0))
10906 return -EINVAL;
10907
10908 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010909 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 if (NULL == hb_params) {
10911 hddLog(LOGE, FL("Request Buffer Alloc Fail"));
10912 return -ENOMEM;
10913 }
10914
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010915 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 smeStatus =
10917 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
10918 hb_params,
10919 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010920 if (QDF_STATUS_SUCCESS != smeStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010921 hddLog(LOGE, "LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010922 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923 }
10924 return 0;
10925 }
10926#endif /* FEATURE_WLAN_LPHB */
10927
10928#if defined(QCA_WIFI_FTM)
10929 case WLAN_HDD_TM_CMD_WLAN_FTM:
10930 {
10931 int buf_len;
10932 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010933 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010934 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
10935 hddLog(LOGE,
10936 FL
10937 ("WLAN_HDD_TM_ATTR_DATA attribute is invalid"));
10938 return -EINVAL;
10939 }
10940
10941 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
10942 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
10943
10944 pr_info("****FTM Tx cmd len = %d*****\n", buf_len);
10945
10946 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
10947
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010948 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010949 err = -EBUSY;
10950 break;
10951 }
10952#endif
10953
10954 default:
10955 hddLog(LOGE, FL("command %d not supported"),
10956 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
10957 return -EOPNOTSUPP;
10958 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010959 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 return err;
10961}
10962
10963/**
10964 * wlan_hdd_cfg80211_testmode() - test mode
10965 * @wiphy: Pointer to wiphy
10966 * @dev: Pointer to network device
10967 * @data: Data pointer
10968 * @len: Data length
10969 *
10970 * Return: 0 for success, non-zero for failure
10971 */
10972static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10973#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
10974 struct wireless_dev *wdev,
10975#endif
10976 void *data, int len)
10977{
10978 int ret;
10979
10980 cds_ssr_protect(__func__);
10981 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
10982 cds_ssr_unprotect(__func__);
10983
10984 return ret;
10985}
10986
10987#if defined(QCA_WIFI_FTM)
10988/**
10989 * wlan_hdd_testmode_rx_event() - test mode rx event handler
10990 * @buf: Pointer to buffer
10991 * @buf_len: Buffer length
10992 *
10993 * Return: none
10994 */
10995void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
10996{
10997 struct sk_buff *skb;
10998 hdd_context_t *hdd_ctx;
10999
11000 if (!buf || !buf_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011001 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 "%s: buf or buf_len invalid, buf = %p buf_len = %zu",
11003 __func__, buf, buf_len);
11004 return;
11005 }
11006
Anurag Chouhan6d760662016-02-20 16:05:43 +053011007 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011009 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011010 "%s: hdd context invalid", __func__);
11011 return;
11012 }
11013
11014 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
11015 buf_len, GFP_KERNEL);
11016 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011017 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011018 "%s: failed to allocate testmode rx skb!", __func__);
11019 return;
11020 }
11021
11022 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
11023 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
11024 goto nla_put_failure;
11025
11026 pr_info("****FTM Rx cmd len = %zu*****\n", buf_len);
11027
11028 cfg80211_testmode_event(skb, GFP_KERNEL);
11029 return;
11030
11031nla_put_failure:
11032 kfree_skb(skb);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011033 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011034 "%s: nla_put failed on testmode rx skb!", __func__);
11035}
11036#endif
11037#endif /* CONFIG_NL80211_TESTMODE */
11038
11039#ifdef QCA_HT_2040_COEX
11040/**
11041 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11042 * @wiphy: Pointer to wiphy
11043 * @dev: Pointer to network device
11044 * @chandef: Pointer to channel definition parameter
11045 *
11046 * Return: 0 for success, non-zero for failure
11047 */
11048static int
11049__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11050 struct net_device *dev,
11051 struct cfg80211_chan_def *chandef)
11052{
11053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11054 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011055 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 tSmeConfigParams sme_config;
11057 bool cbModeChange;
11058
Anurag Chouhan6d760662016-02-20 16:05:43 +053011059 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011060 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11061 return -EINVAL;
11062 }
11063
11064 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11065 status = wlan_hdd_validate_context(pHddCtx);
11066
11067 if (0 != status) {
11068 hddLog(LOGE, FL("HDD context is not valid"));
11069 return status;
11070 }
11071
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011072 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073 sme_get_config_param(pHddCtx->hHal, &sme_config);
11074 switch (chandef->width) {
11075 case NL80211_CHAN_WIDTH_20:
11076 if (sme_config.csrConfig.channelBondingMode24GHz !=
11077 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11078 sme_config.csrConfig.channelBondingMode24GHz =
11079 eCSR_INI_SINGLE_CHANNEL_CENTERED;
11080 sme_update_config(pHddCtx->hHal, &sme_config);
11081 cbModeChange = true;
11082 }
11083 break;
11084
11085 case NL80211_CHAN_WIDTH_40:
11086 if (sme_config.csrConfig.channelBondingMode24GHz ==
11087 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11088 if (NL80211_CHAN_HT40MINUS ==
11089 cfg80211_get_chandef_type(chandef))
11090 sme_config.csrConfig.channelBondingMode24GHz =
11091 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
11092 else
11093 sme_config.csrConfig.channelBondingMode24GHz =
11094 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
11095 sme_update_config(pHddCtx->hHal, &sme_config);
11096 cbModeChange = true;
11097 }
11098 break;
11099
11100 default:
11101 hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !"));
11102 return -EINVAL;
11103 }
11104
11105 if (!cbModeChange)
11106 return 0;
11107
11108 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
11109 return 0;
11110
11111 hddLog(LOG1, FL("Channel bonding changed to %d"),
11112 sme_config.csrConfig.channelBondingMode24GHz);
11113
11114 /* Change SAP ht2040 mode */
11115 status = hdd_set_sap_ht2040_mode(pAdapter,
11116 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011117 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118 hddLog(LOGE, FL("Error!!! Cannot set SAP HT20/40 mode!"));
11119 return -EINVAL;
11120 }
11121
11122 return 0;
11123}
11124
11125/**
11126 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11127 * @wiphy: Pointer to wiphy
11128 * @dev: Pointer to network device
11129 * @chandef: Pointer to channel definition parameter
11130 *
11131 * Return: 0 for success, non-zero for failure
11132 */
11133static int
11134wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11135 struct net_device *dev,
11136 struct cfg80211_chan_def *chandef)
11137{
11138 int ret;
11139
11140 cds_ssr_protect(__func__);
11141 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
11142 cds_ssr_unprotect(__func__);
11143
11144 return ret;
11145}
11146#endif
11147
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011148#ifdef CHANNEL_SWITCH_SUPPORTED
11149/**
11150 * __wlan_hdd_cfg80211_channel_switch()- function to switch
11151 * channel in SAP/GO
11152 * @wiphy: wiphy pointer
11153 * @dev: dev pointer.
11154 * @csa_params: Change channel params
11155 *
11156 * This function is called to switch channel in SAP/GO
11157 *
11158 * Return: 0 if success else return non zero
11159 */
11160static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11161 struct net_device *dev,
11162 struct cfg80211_csa_settings *csa_params)
11163{
11164 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
11165 hdd_context_t *hdd_ctx;
11166 uint8_t channel;
11167 uint16_t freq;
11168 int ret;
Amar Singhale4f28ee2015-10-21 14:36:56 -070011169 enum ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011170
11171 hddLog(LOG1, FL("Set Freq %d"),
11172 csa_params->chandef.chan->center_freq);
11173
11174 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11175 ret = wlan_hdd_validate_context(hdd_ctx);
11176
11177 if (0 != ret)
11178 return ret;
11179
11180 if ((WLAN_HDD_P2P_GO != adapter->device_mode) &&
11181 (WLAN_HDD_SOFTAP != adapter->device_mode))
11182 return -ENOTSUPP;
11183
11184 freq = csa_params->chandef.chan->center_freq;
11185 channel = cds_freq_to_chan(freq);
11186
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053011187 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
11188
11189 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011190 return ret;
11191}
11192
11193/**
11194 * wlan_hdd_cfg80211_channel_switch()- function to switch
11195 * channel in SAP/GO
11196 * @wiphy: wiphy pointer
11197 * @dev: dev pointer.
11198 * @csa_params: Change channel params
11199 *
11200 * This function is called to switch channel in SAP/GO
11201 *
11202 * Return: 0 if success else return non zero
11203 */
11204static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11205 struct net_device *dev,
11206 struct cfg80211_csa_settings *csa_params)
11207{
11208 int ret;
11209
11210 cds_ssr_protect(__func__);
11211 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
11212 cds_ssr_unprotect(__func__);
11213 return ret;
11214}
11215#endif
11216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011217/**
11218 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
11219 * translation from NL to policy manager type
11220 * @type: Generic connection mode type defined in NL
11221 *
11222 *
11223 * This function provides the type translation
11224 *
11225 * Return: cds_con_mode enum
11226 */
11227enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
11228 enum nl80211_iftype type)
11229{
11230 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
11231 switch (type) {
11232 case NL80211_IFTYPE_STATION:
11233 mode = CDS_STA_MODE;
11234 break;
11235 case NL80211_IFTYPE_P2P_CLIENT:
11236 mode = CDS_P2P_CLIENT_MODE;
11237 break;
11238 case NL80211_IFTYPE_P2P_GO:
11239 mode = CDS_P2P_GO_MODE;
11240 break;
11241 case NL80211_IFTYPE_AP:
11242 mode = CDS_SAP_MODE;
11243 break;
11244 case NL80211_IFTYPE_ADHOC:
11245 mode = CDS_IBSS_MODE;
11246 break;
11247 default:
11248 hddLog(LOGE, FL("Unsupported interface type (%d)"),
11249 type);
11250 }
11251 return mode;
11252}
11253
11254/**
11255 * struct cfg80211_ops - cfg80211_ops
11256 *
11257 * @add_virtual_intf: Add virtual interface
11258 * @del_virtual_intf: Delete virtual interface
11259 * @change_virtual_intf: Change virtual interface
11260 * @change_station: Change station
11261 * @add_beacon: Add beacon in sap mode
11262 * @del_beacon: Delete beacon in sap mode
11263 * @set_beacon: Set beacon in sap mode
11264 * @start_ap: Start ap
11265 * @change_beacon: Change beacon
11266 * @stop_ap: Stop ap
11267 * @change_bss: Change bss
11268 * @add_key: Add key
11269 * @get_key: Get key
11270 * @del_key: Delete key
11271 * @set_default_key: Set default key
11272 * @set_channel: Set channel
11273 * @scan: Scan
11274 * @connect: Connect
11275 * @disconnect: Disconnect
11276 * @join_ibss = Join ibss
11277 * @leave_ibss = Leave ibss
11278 * @set_wiphy_params = Set wiphy params
11279 * @set_tx_power = Set tx power
11280 * @get_tx_power = get tx power
11281 * @remain_on_channel = Remain on channel
11282 * @cancel_remain_on_channel = Cancel remain on channel
11283 * @mgmt_tx = Tx management frame
11284 * @mgmt_tx_cancel_wait = Cancel management tx wait
11285 * @set_default_mgmt_key = Set default management key
11286 * @set_txq_params = Set tx queue parameters
11287 * @get_station = Get station
11288 * @set_power_mgmt = Set power management
11289 * @del_station = Delete station
11290 * @add_station = Add station
11291 * @set_pmksa = Set pmksa
11292 * @del_pmksa = Delete pmksa
11293 * @flush_pmksa = Flush pmksa
11294 * @update_ft_ies = Update FT IEs
11295 * @tdls_mgmt = Tdls management
11296 * @tdls_oper = Tdls operation
11297 * @set_rekey_data = Set rekey data
11298 * @sched_scan_start = Scheduled scan start
11299 * @sched_scan_stop = Scheduled scan stop
11300 * @resume = Resume wlan
11301 * @suspend = Suspend wlan
11302 * @set_mac_acl = Set mac acl
11303 * @testmode_cmd = Test mode command
11304 * @set_ap_chanwidth = Set AP channel bandwidth
11305 * @dump_survey = Dump survey
11306 * @key_mgmt_set_pmk = Set pmk key management
11307 */
11308static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
11309 .add_virtual_intf = wlan_hdd_add_virtual_intf,
11310 .del_virtual_intf = wlan_hdd_del_virtual_intf,
11311 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
11312 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011313 .start_ap = wlan_hdd_cfg80211_start_ap,
11314 .change_beacon = wlan_hdd_cfg80211_change_beacon,
11315 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011316 .change_bss = wlan_hdd_cfg80211_change_bss,
11317 .add_key = wlan_hdd_cfg80211_add_key,
11318 .get_key = wlan_hdd_cfg80211_get_key,
11319 .del_key = wlan_hdd_cfg80211_del_key,
11320 .set_default_key = wlan_hdd_cfg80211_set_default_key,
11321 .scan = wlan_hdd_cfg80211_scan,
11322 .connect = wlan_hdd_cfg80211_connect,
11323 .disconnect = wlan_hdd_cfg80211_disconnect,
11324 .join_ibss = wlan_hdd_cfg80211_join_ibss,
11325 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
11326 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
11327 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
11328 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
11329 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
11330 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
11331 .mgmt_tx = wlan_hdd_mgmt_tx,
11332 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
11333 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
11334 .set_txq_params = wlan_hdd_set_txq_params,
11335 .get_station = wlan_hdd_cfg80211_get_station,
11336 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
11337 .del_station = wlan_hdd_cfg80211_del_station,
11338 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
11340 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
11341 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080011342#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011343 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
11344#endif
11345#ifdef FEATURE_WLAN_TDLS
11346 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
11347 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
11348#endif
11349#ifdef WLAN_FEATURE_GTK_OFFLOAD
11350 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
11351#endif /* WLAN_FEATURE_GTK_OFFLOAD */
11352#ifdef FEATURE_WLAN_SCAN_PNO
11353 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
11354 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
11355#endif /*FEATURE_WLAN_SCAN_PNO */
11356 .resume = wlan_hdd_cfg80211_resume_wlan,
11357 .suspend = wlan_hdd_cfg80211_suspend_wlan,
11358 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
11359#ifdef WLAN_NL80211_TESTMODE
11360 .testmode_cmd = wlan_hdd_cfg80211_testmode,
11361#endif
11362#ifdef QCA_HT_2040_COEX
11363 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
11364#endif
11365 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011366#ifdef CHANNEL_SWITCH_SUPPORTED
11367 .channel_switch = wlan_hdd_cfg80211_channel_switch,
11368#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011369};