blob: 104aa9396064063ea1d9c7f179c02464c58ac9e2 [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
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530140#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142static const u32 hdd_cipher_suites[] = {
143 WLAN_CIPHER_SUITE_WEP40,
144 WLAN_CIPHER_SUITE_WEP104,
145 WLAN_CIPHER_SUITE_TKIP,
146#ifdef FEATURE_WLAN_ESE
147#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
148#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
149 WLAN_CIPHER_SUITE_BTK,
150 WLAN_CIPHER_SUITE_KRK,
151 WLAN_CIPHER_SUITE_CCMP,
152#else
153 WLAN_CIPHER_SUITE_CCMP,
154#endif
155#ifdef FEATURE_WLAN_WAPI
156 WLAN_CIPHER_SUITE_SMS4,
157#endif
158#ifdef WLAN_FEATURE_11W
159 WLAN_CIPHER_SUITE_AES_CMAC,
160#endif
161};
162
163static struct ieee80211_channel hdd_channels_2_4_ghz[] = {
164 HDD2GHZCHAN(2412, 1, 0),
165 HDD2GHZCHAN(2417, 2, 0),
166 HDD2GHZCHAN(2422, 3, 0),
167 HDD2GHZCHAN(2427, 4, 0),
168 HDD2GHZCHAN(2432, 5, 0),
169 HDD2GHZCHAN(2437, 6, 0),
170 HDD2GHZCHAN(2442, 7, 0),
171 HDD2GHZCHAN(2447, 8, 0),
172 HDD2GHZCHAN(2452, 9, 0),
173 HDD2GHZCHAN(2457, 10, 0),
174 HDD2GHZCHAN(2462, 11, 0),
175 HDD2GHZCHAN(2467, 12, 0),
176 HDD2GHZCHAN(2472, 13, 0),
177 HDD2GHZCHAN(2484, 14, 0),
178};
179
180static struct ieee80211_channel hdd_social_channels_2_4_ghz[] = {
181 HDD2GHZCHAN(2412, 1, 0),
182 HDD2GHZCHAN(2437, 6, 0),
183 HDD2GHZCHAN(2462, 11, 0),
184};
185
186static struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 HDD5GHZCHAN(5180, 36, 0),
188 HDD5GHZCHAN(5200, 40, 0),
189 HDD5GHZCHAN(5220, 44, 0),
190 HDD5GHZCHAN(5240, 48, 0),
191 HDD5GHZCHAN(5260, 52, 0),
192 HDD5GHZCHAN(5280, 56, 0),
193 HDD5GHZCHAN(5300, 60, 0),
194 HDD5GHZCHAN(5320, 64, 0),
195 HDD5GHZCHAN(5500, 100, 0),
196 HDD5GHZCHAN(5520, 104, 0),
197 HDD5GHZCHAN(5540, 108, 0),
198 HDD5GHZCHAN(5560, 112, 0),
199 HDD5GHZCHAN(5580, 116, 0),
200 HDD5GHZCHAN(5600, 120, 0),
201 HDD5GHZCHAN(5620, 124, 0),
202 HDD5GHZCHAN(5640, 128, 0),
203 HDD5GHZCHAN(5660, 132, 0),
204 HDD5GHZCHAN(5680, 136, 0),
205 HDD5GHZCHAN(5700, 140, 0),
206 HDD5GHZCHAN(5720, 144, 0),
207 HDD5GHZCHAN(5745, 149, 0),
208 HDD5GHZCHAN(5765, 153, 0),
209 HDD5GHZCHAN(5785, 157, 0),
210 HDD5GHZCHAN(5805, 161, 0),
211 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212 HDD5GHZCHAN(5852, 170, 0),
213 HDD5GHZCHAN(5855, 171, 0),
214 HDD5GHZCHAN(5860, 172, 0),
215 HDD5GHZCHAN(5865, 173, 0),
216 HDD5GHZCHAN(5870, 174, 0),
217 HDD5GHZCHAN(5875, 175, 0),
218 HDD5GHZCHAN(5880, 176, 0),
219 HDD5GHZCHAN(5885, 177, 0),
220 HDD5GHZCHAN(5890, 178, 0),
221 HDD5GHZCHAN(5895, 179, 0),
222 HDD5GHZCHAN(5900, 180, 0),
223 HDD5GHZCHAN(5905, 181, 0),
224 HDD5GHZCHAN(5910, 182, 0),
225 HDD5GHZCHAN(5915, 183, 0),
226 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227};
228
229static struct ieee80211_rate g_mode_rates[] = {
230 HDD_G_MODE_RATETAB(10, 0x1, 0),
231 HDD_G_MODE_RATETAB(20, 0x2, 0),
232 HDD_G_MODE_RATETAB(55, 0x4, 0),
233 HDD_G_MODE_RATETAB(110, 0x8, 0),
234 HDD_G_MODE_RATETAB(60, 0x10, 0),
235 HDD_G_MODE_RATETAB(90, 0x20, 0),
236 HDD_G_MODE_RATETAB(120, 0x40, 0),
237 HDD_G_MODE_RATETAB(180, 0x80, 0),
238 HDD_G_MODE_RATETAB(240, 0x100, 0),
239 HDD_G_MODE_RATETAB(360, 0x200, 0),
240 HDD_G_MODE_RATETAB(480, 0x400, 0),
241 HDD_G_MODE_RATETAB(540, 0x800, 0),
242};
243
244static struct ieee80211_rate a_mode_rates[] = {
245 HDD_G_MODE_RATETAB(60, 0x10, 0),
246 HDD_G_MODE_RATETAB(90, 0x20, 0),
247 HDD_G_MODE_RATETAB(120, 0x40, 0),
248 HDD_G_MODE_RATETAB(180, 0x80, 0),
249 HDD_G_MODE_RATETAB(240, 0x100, 0),
250 HDD_G_MODE_RATETAB(360, 0x200, 0),
251 HDD_G_MODE_RATETAB(480, 0x400, 0),
252 HDD_G_MODE_RATETAB(540, 0x800, 0),
253};
254
255static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
256 .channels = hdd_channels_2_4_ghz,
257 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
258 .band = IEEE80211_BAND_2GHZ,
259 .bitrates = g_mode_rates,
260 .n_bitrates = g_mode_rates_size,
261 .ht_cap.ht_supported = 1,
262 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
263 | IEEE80211_HT_CAP_GRN_FLD
264 | IEEE80211_HT_CAP_DSSSCCK40
265 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
266 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
267 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
268 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
269 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
270 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
271 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
272};
273
274static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_ghz = {
275 .channels = hdd_social_channels_2_4_ghz,
276 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_ghz),
277 .band = IEEE80211_BAND_2GHZ,
278 .bitrates = g_mode_rates,
279 .n_bitrates = g_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
284 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
285 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
286 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
287 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
288 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
289};
290
291static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
292 .channels = hdd_channels_5_ghz,
293 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
294 .band = IEEE80211_BAND_5GHZ,
295 .bitrates = a_mode_rates,
296 .n_bitrates = a_mode_rates_size,
297 .ht_cap.ht_supported = 1,
298 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
299 | IEEE80211_HT_CAP_GRN_FLD
300 | IEEE80211_HT_CAP_DSSSCCK40
301 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
302 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
303 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
304 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
305 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
306 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
307 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
308 .vht_cap.vht_supported = 1,
309};
310
311/* This structure contain information what kind of frame are expected in
312 TX/RX direction for each kind of interface */
313static const struct ieee80211_txrx_stypes
314 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
315 [NL80211_IFTYPE_STATION] = {
316 .tx = 0xffff,
317 .rx = BIT(SIR_MAC_MGMT_ACTION) |
318 BIT(SIR_MAC_MGMT_PROBE_REQ),
319 },
320 [NL80211_IFTYPE_AP] = {
321 .tx = 0xffff,
322 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
323 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ) |
325 BIT(SIR_MAC_MGMT_DISASSOC) |
326 BIT(SIR_MAC_MGMT_AUTH) |
327 BIT(SIR_MAC_MGMT_DEAUTH) |
328 BIT(SIR_MAC_MGMT_ACTION),
329 },
330 [NL80211_IFTYPE_ADHOC] = {
331 .tx = 0xffff,
332 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
334 BIT(SIR_MAC_MGMT_PROBE_REQ) |
335 BIT(SIR_MAC_MGMT_DISASSOC) |
336 BIT(SIR_MAC_MGMT_AUTH) |
337 BIT(SIR_MAC_MGMT_DEAUTH) |
338 BIT(SIR_MAC_MGMT_ACTION),
339 },
340 [NL80211_IFTYPE_P2P_CLIENT] = {
341 .tx = 0xffff,
342 .rx = BIT(SIR_MAC_MGMT_ACTION) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ),
344 },
345 [NL80211_IFTYPE_P2P_GO] = {
346 /* This is also same as for SoftAP */
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
349 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
350 BIT(SIR_MAC_MGMT_PROBE_REQ) |
351 BIT(SIR_MAC_MGMT_DISASSOC) |
352 BIT(SIR_MAC_MGMT_AUTH) |
353 BIT(SIR_MAC_MGMT_DEAUTH) |
354 BIT(SIR_MAC_MGMT_ACTION),
355 },
356};
357
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800358/* Interface limits and combinations registered by the driver */
359
360/* STA ( + STA ) combination */
361static const struct ieee80211_iface_limit
362 wlan_hdd_sta_iface_limit[] = {
363 {
364 .max = 3, /* p2p0 is a STA as well */
365 .types = BIT(NL80211_IFTYPE_STATION),
366 },
367};
368
Krunal Soni7bc4f912015-11-15 23:41:56 -0800369#ifndef QCA_WIFI_3_0_EMU
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370/* ADHOC (IBSS) limit */
371static const struct ieee80211_iface_limit
372 wlan_hdd_adhoc_iface_limit[] = {
373 {
374 .max = 1,
375 .types = BIT(NL80211_IFTYPE_STATION),
376 },
377 {
378 .max = 1,
379 .types = BIT(NL80211_IFTYPE_ADHOC),
380 },
381};
Krunal Soni7bc4f912015-11-15 23:41:56 -0800382#else
383/* ADHOC (IBSS) limit */
384static const struct ieee80211_iface_limit
385 wlan_hdd_adhoc_iface_limit[] = {
386 {
387 .max = 1,
388 .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
389 },
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_ADHOC),
393 },
394};
395#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396
397/* AP ( + AP ) combination */
398static const struct ieee80211_iface_limit
399 wlan_hdd_ap_iface_limit[] = {
400 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530401 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402 .types = BIT(NL80211_IFTYPE_AP),
403 },
404};
405
406/* P2P limit */
407static const struct ieee80211_iface_limit
408 wlan_hdd_p2p_iface_limit[] = {
409 {
410 .max = 1,
411 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
412 },
413 {
414 .max = 1,
415 .types = BIT(NL80211_IFTYPE_P2P_GO),
416 },
417};
418
419static const struct ieee80211_iface_limit
420 wlan_hdd_sta_ap_iface_limit[] = {
421 {
422 /* We need 1 extra STA interface for OBSS scan when SAP starts
423 * with HT40 in STA+SAP concurrency mode
424 */
425 .max = (1 + SAP_MAX_OBSS_STA_CNT),
426 .types = BIT(NL80211_IFTYPE_STATION),
427 },
428 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530429 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 .types = BIT(NL80211_IFTYPE_AP),
431 },
432};
433
434/* STA + P2P combination */
435static const struct ieee80211_iface_limit
436 wlan_hdd_sta_p2p_iface_limit[] = {
437 {
438 /* One reserved for dedicated P2PDEV usage */
439 .max = 2,
440 .types = BIT(NL80211_IFTYPE_STATION)
441 },
442 {
443 /* Support for two identical (GO + GO or CLI + CLI)
444 * or dissimilar (GO + CLI) P2P interfaces
445 */
446 .max = 2,
447 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
448 },
449};
450
451/* STA + AP + P2PGO combination */
452static const struct ieee80211_iface_limit
453wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
454 /* Support for AP+P2PGO interfaces */
455 {
456 .max = 2,
457 .types = BIT(NL80211_IFTYPE_STATION)
458 },
459 {
460 .max = 1,
461 .types = BIT(NL80211_IFTYPE_P2P_GO)
462 },
463 {
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_AP)
466 }
467};
468
469/* SAP + P2P combination */
470static const struct ieee80211_iface_limit
471wlan_hdd_sap_p2p_iface_limit[] = {
472 {
473 /* 1 dedicated for p2p0 which is a STA type */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_STATION)
476 },
477 {
478 /* The p2p interface in SAP+P2P can be GO/CLI.
479 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
480 */
481 .max = 1,
482 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
483 },
484 {
485 /* SAP+GO to support only one SAP interface */
486 .max = 1,
487 .types = BIT(NL80211_IFTYPE_AP)
488 }
489};
490
491/* P2P + P2P combination */
492static const struct ieee80211_iface_limit
493wlan_hdd_p2p_p2p_iface_limit[] = {
494 {
495 /* 1 dedicated for p2p0 which is a STA type */
496 .max = 1,
497 .types = BIT(NL80211_IFTYPE_STATION)
498 },
499 {
500 /* The p2p interface in P2P+P2P can be GO/CLI.
501 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
502 */
503 .max = 2,
504 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
505 },
506};
507
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700508static const struct ieee80211_iface_limit
509 wlan_hdd_mon_iface_limit[] = {
510 {
511 .max = 3, /* Monitor interface */
512 .types = BIT(NL80211_IFTYPE_MONITOR),
513 },
514};
515
516static struct ieee80211_iface_combination
517 wlan_hdd_mon_iface[] = {
518 {
519 .limits = wlan_hdd_mon_iface_limit,
520 .max_interfaces = 3,
521 .num_different_channels = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
523 },
524};
525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526static struct ieee80211_iface_combination
527 wlan_hdd_iface_combination[] = {
528 /* STA */
529 {
530 .limits = wlan_hdd_sta_iface_limit,
531 .num_different_channels = 2,
532 .max_interfaces = 3,
533 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
534 },
535 /* ADHOC */
536 {
537 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700538 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 .max_interfaces = 2,
540 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
541 },
542 /* AP */
543 {
544 .limits = wlan_hdd_ap_iface_limit,
545 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530546 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
548 },
549 /* P2P */
550 {
551 .limits = wlan_hdd_p2p_iface_limit,
552 .num_different_channels = 2,
553 .max_interfaces = 2,
554 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
555 },
556 /* STA + AP */
557 {
558 .limits = wlan_hdd_sta_ap_iface_limit,
559 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530560 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
562 .beacon_int_infra_match = true,
563 },
564 /* STA + P2P */
565 {
566 .limits = wlan_hdd_sta_p2p_iface_limit,
567 .num_different_channels = 2,
568 /* one interface reserved for P2PDEV dedicated usage */
569 .max_interfaces = 4,
570 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
571 .beacon_int_infra_match = true,
572 },
573 /* STA + P2P GO + SAP */
574 {
575 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
576 /* we can allow 3 channels for three different persona
577 * but due to firmware limitation, allow max 2 concrnt channels.
578 */
579 .num_different_channels = 2,
580 /* one interface reserved for P2PDEV dedicated usage */
581 .max_interfaces = 4,
582 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
583 .beacon_int_infra_match = true,
584 },
585 /* SAP + P2P */
586 {
587 .limits = wlan_hdd_sap_p2p_iface_limit,
588 .num_different_channels = 2,
589 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
590 .max_interfaces = 3,
591 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
592 .beacon_int_infra_match = true,
593 },
594 /* P2P + P2P */
595 {
596 .limits = wlan_hdd_p2p_p2p_iface_limit,
597 .num_different_channels = 2,
598 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
599 .max_interfaces = 3,
600 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
601 .beacon_int_infra_match = true,
602 },
603};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604
605static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530606struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607
608#ifdef WLAN_NL80211_TESTMODE
609enum wlan_hdd_tm_attr {
610 WLAN_HDD_TM_ATTR_INVALID = 0,
611 WLAN_HDD_TM_ATTR_CMD = 1,
612 WLAN_HDD_TM_ATTR_DATA = 2,
613 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
614 WLAN_HDD_TM_ATTR_TYPE = 4,
615 /* keep last */
616 WLAN_HDD_TM_ATTR_AFTER_LAST,
617 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
618};
619
620enum wlan_hdd_tm_cmd {
621 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
622 WLAN_HDD_TM_CMD_WLAN_HB = 1,
623};
624
625#define WLAN_HDD_TM_DATA_MAX_LEN 5000
626
627static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
628 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
629 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
630 .len = WLAN_HDD_TM_DATA_MAX_LEN},
631};
632#endif /* WLAN_NL80211_TESTMODE */
633
634#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
635static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
636 .flags = WIPHY_WOWLAN_MAGIC_PKT,
637 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
638 .pattern_min_len = 1,
639 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
640};
641#endif
642
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530644 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
645 * @flags: Pointer to the flags to Add channel switch flag.
646 *
647 * This Function adds Channel Switch support flag, if channel switch is
648 * supported by kernel.
649 * Return: void.
650 */
651#ifdef CHANNEL_SWITCH_SUPPORTED
652static inline void hdd_add_channel_switch_support(uint32_t *flags)
653{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800654 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655 return;
656}
657#else
658static inline void hdd_add_channel_switch_support(uint32_t *flags)
659{
660 return;
661}
662#endif
663
Manikandan Mohan22b83722015-12-15 15:03:23 -0800664#ifdef FEATURE_WLAN_TDLS
665
666/* TDLS capabilities params */
667#define PARAM_MAX_TDLS_SESSION \
668 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
669#define PARAM_TDLS_FEATURE_SUPPORT \
670 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
671
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530672/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
674 * @wiphy: WIPHY structure pointer
675 * @wdev: Wireless device structure pointer
676 * @data: Pointer to the data received
677 * @data_len: Length of the data received
678 *
679 * This function provides TDLS capabilities
680 *
681 * Return: 0 on success and errno on failure
682 */
683static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
684 struct wireless_dev *wdev,
685 const void *data,
686 int data_len)
687{
688 int status;
689 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
690 struct sk_buff *skb;
691 uint32_t set = 0;
692
Jeff Johnson1f61b612016-02-12 16:28:33 -0800693 ENTER_DEV(wdev->netdev);
694
Anurag Chouhan6d760662016-02-20 16:05:43 +0530695 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 hdd_err("Command not allowed in FTM mode");
697 return -EPERM;
698 }
699
700 status = wlan_hdd_validate_context(hdd_ctx);
701 if (status)
702 return status;
703
704 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
705 NLMSG_HDRLEN);
706 if (!skb) {
707 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
708 goto fail;
709 }
710
711 if (false == hdd_ctx->config->fEnableTDLSSupport) {
712 hddLog(LOGE,
713 FL("TDLS feature not Enabled or Not supported in FW"));
714 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
715 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
716 hddLog(LOGE, FL("nla put fail"));
717 goto fail;
718 }
719 } else {
720 set = set | WIFI_TDLS_SUPPORT;
721 set = set | (hdd_ctx->config->fTDLSExternalControl ?
722 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
723 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
724 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
725 hddLog(LOG1, FL("TDLS Feature supported value %x"), set);
726 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
727 hdd_ctx->max_num_tdls_sta) ||
728 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
729 set)) {
730 hddLog(LOGE, FL("nla put fail"));
731 goto fail;
732 }
733 }
734 return cfg80211_vendor_cmd_reply(skb);
735fail:
736 if (skb)
737 kfree_skb(skb);
738 return -EINVAL;
739}
740
741/**
742 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
743 * @wiphy: WIPHY structure pointer
744 * @wdev: Wireless device structure pointer
745 * @data: Pointer to the data received
746 * @data_len: Length of the data received
747 *
748 * This function provides TDLS capabilities
749 *
750 * Return: 0 on success and errno on failure
751 */
752static int
753wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
754 struct wireless_dev *wdev,
755 const void *data,
756 int data_len)
757{
758 int ret;
759
760 cds_ssr_protect(__func__);
761 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
762 data, data_len);
763 cds_ssr_unprotect(__func__);
764
765 return ret;
766}
767#endif
768
769#ifdef QCA_HT_2040_COEX
770static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
771#endif
772
773#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
774/*
775 * FUNCTION: wlan_hdd_send_avoid_freq_event
776 * This is called when wlan driver needs to send vendor specific
777 * avoid frequency range event to userspace
778 */
779int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
780 tHddAvoidFreqList *pAvoidFreqList)
781{
782 struct sk_buff *vendor_event;
783
784 ENTER();
785
786 if (!pHddCtx) {
787 hddLog(LOGE, FL("HDD context is null"));
788 return -EINVAL;
789 }
790
791 if (!pAvoidFreqList) {
792 hddLog(LOGE, FL("pAvoidFreqList is null"));
793 return -EINVAL;
794 }
795
796 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
797 NULL,
798 sizeof(tHddAvoidFreqList),
799 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
800 GFP_KERNEL);
801 if (!vendor_event) {
802 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
803 return -EINVAL;
804 }
805
806 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
807 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
808
809 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
810
811 EXIT();
812 return 0;
813}
814#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
815
816/* vendor specific events */
817static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
818#ifdef FEATURE_WLAN_CH_AVOID
819 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
824 },
825#endif /* FEATURE_WLAN_CH_AVOID */
826
827#ifdef WLAN_FEATURE_NAN
828 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
829 .vendor_id =
830 QCA_NL80211_VENDOR_ID,
831 .subcmd =
832 QCA_NL80211_VENDOR_SUBCMD_NAN
833 },
834#endif
835
836#ifdef WLAN_FEATURE_STATS_EXT
837 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
838 .vendor_id =
839 QCA_NL80211_VENDOR_ID,
840 .subcmd =
841 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
842 },
843#endif /* WLAN_FEATURE_STATS_EXT */
844#ifdef FEATURE_WLAN_EXTSCAN
845 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
846 .vendor_id =
847 QCA_NL80211_VENDOR_ID,
848 .subcmd =
849 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
850 },
851 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
852 .vendor_id =
853 QCA_NL80211_VENDOR_ID,
854 .subcmd =
855 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
856 },
857 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
858 .
859 vendor_id
860 =
861 QCA_NL80211_VENDOR_ID,
862 .subcmd =
863 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
864 },
865 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
866 .
867 vendor_id
868 =
869 QCA_NL80211_VENDOR_ID,
870 .
871 subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
875 .
876 vendor_id
877 =
878 QCA_NL80211_VENDOR_ID,
879 .
880 subcmd
881 =
882 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
883 },
884 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
885 .
886 vendor_id
887 =
888 QCA_NL80211_VENDOR_ID,
889 .subcmd =
890 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
891 },
892 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
893 .vendor_id =
894 QCA_NL80211_VENDOR_ID,
895 .subcmd =
896 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
897 },
898 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
899 .
900 vendor_id
901 =
902 QCA_NL80211_VENDOR_ID,
903 .subcmd =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .subcmd =
912 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
913 },
914 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
915 .
916 vendor_id
917 =
918 QCA_NL80211_VENDOR_ID,
919 .
920 subcmd
921 =
922 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
923 },
924 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
925 .
926 vendor_id
927 =
928 QCA_NL80211_VENDOR_ID,
929 .
930 subcmd =
931 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
932 },
933 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
934 .
935 vendor_id
936 =
937 QCA_NL80211_VENDOR_ID,
938 .
939 subcmd
940 =
941 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
942 },
943 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
944 .
945 vendor_id
946 =
947 QCA_NL80211_VENDOR_ID,
948 .
949 subcmd
950 =
951 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
952 },
953 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
954 .vendor_id = QCA_NL80211_VENDOR_ID,
955 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
956 },
957 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
958 .vendor_id = QCA_NL80211_VENDOR_ID,
959 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
960 },
961#endif /* FEATURE_WLAN_EXTSCAN */
962
963#ifdef WLAN_FEATURE_LINK_LAYER_STATS
964 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
981 },
982 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
987 },
988 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
989 .vendor_id =
990 QCA_NL80211_VENDOR_ID,
991 .subcmd =
992 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
993 },
994 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
999 },
1000#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1001 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1008 .vendor_id = QCA_NL80211_VENDOR_ID,
1009 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1010 },
1011#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1012 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1017 },
1018#endif
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1030 },
1031 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1032 .vendor_id =
1033 QCA_NL80211_VENDOR_ID,
1034 .subcmd =
1035 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1036 },
1037 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1038 .vendor_id =
1039 QCA_NL80211_VENDOR_ID,
1040 .subcmd =
1041 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1042 },
1043 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1044 .vendor_id =
1045 QCA_NL80211_VENDOR_ID,
1046 .subcmd =
1047 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1048 },
1049#ifdef FEATURE_WLAN_EXTSCAN
1050 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1057 },
1058 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1061 },
1062 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1063 .vendor_id = QCA_NL80211_VENDOR_ID,
1064 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1065 },
1066 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1069 },
1070#endif /* FEATURE_WLAN_EXTSCAN */
1071 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1072 .vendor_id = QCA_NL80211_VENDOR_ID,
1073 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1074 },
1075#ifdef WLAN_FEATURE_MEMDUMP
1076 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1077 .vendor_id = QCA_NL80211_VENDOR_ID,
1078 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1079 },
1080#endif /* WLAN_FEATURE_MEMDUMP */
1081 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1082 .vendor_id = QCA_NL80211_VENDOR_ID,
1083 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1084 },
1085 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1086 .vendor_id = QCA_NL80211_VENDOR_ID,
1087 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1088 },
1089 /* OCB events */
1090 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1093 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001094#ifdef FEATURE_LFR_SUBNET_DETECTION
1095 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1098 },
1099#endif /*FEATURE_LFR_SUBNET_DETECTION */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100};
1101
1102/**
1103 * __is_driver_dfs_capable() - get driver DFS capability
1104 * @wiphy: pointer to wireless wiphy structure.
1105 * @wdev: pointer to wireless_dev structure.
1106 * @data: Pointer to the data to be passed via vendor interface
1107 * @data_len:Length of the data to be passed
1108 *
1109 * This function is called by userspace to indicate whether or not
1110 * the driver supports DFS offload.
1111 *
1112 * Return: 0 on success, negative errno on failure
1113 */
1114static int __is_driver_dfs_capable(struct wiphy *wiphy,
1115 struct wireless_dev *wdev,
1116 const void *data,
1117 int data_len)
1118{
1119 u32 dfs_capability = 0;
1120 struct sk_buff *temp_skbuff;
1121 int ret_val;
1122 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1123
Jeff Johnson1f61b612016-02-12 16:28:33 -08001124 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001125
1126 ret_val = wlan_hdd_validate_context(hdd_ctx);
1127 if (ret_val)
1128 return ret_val;
1129
Anurag Chouhan6d760662016-02-20 16:05:43 +05301130 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131 hdd_err("Command not allowed in FTM mode");
1132 return -EPERM;
1133 }
1134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136
1137 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1138 NLMSG_HDRLEN);
1139
1140 if (temp_skbuff != NULL) {
1141 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1142 dfs_capability);
1143 if (ret_val) {
1144 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail"));
1145 kfree_skb(temp_skbuff);
1146
1147 return ret_val;
1148 }
1149
1150 return cfg80211_vendor_cmd_reply(temp_skbuff);
1151 }
1152
1153 hddLog(LOGE, FL("dfs capability: buffer alloc fail"));
1154 return -ENOMEM;
1155}
1156
1157/**
1158 * is_driver_dfs_capable() - get driver DFS capability
1159 * @wiphy: pointer to wireless wiphy structure.
1160 * @wdev: pointer to wireless_dev structure.
1161 * @data: Pointer to the data to be passed via vendor interface
1162 * @data_len:Length of the data to be passed
1163 *
1164 * This function is called by userspace to indicate whether or not
1165 * the driver supports DFS offload. This is an SSR-protected
1166 * wrapper function.
1167 *
1168 * Return: 0 on success, negative errno on failure
1169 */
1170static int is_driver_dfs_capable(struct wiphy *wiphy,
1171 struct wireless_dev *wdev,
1172 const void *data,
1173 int data_len)
1174{
1175 int ret;
1176
1177 cds_ssr_protect(__func__);
1178 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1179 cds_ssr_unprotect(__func__);
1180
1181 return ret;
1182}
1183
1184/**
1185 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1186 *
1187 * @adapter: SAP adapter pointer
1188 *
1189 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1190 * radio. So in case of DFS MCC scenario override current SAP given config
1191 * to follow concurrent SAP DFS config
1192 *
1193 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1194 */
1195
1196#ifdef WLAN_FEATURE_MBSSID
1197int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1198{
1199 hdd_adapter_t *con_sap_adapter;
1200 tsap_Config_t *sap_config, *con_sap_config;
1201 int con_ch;
1202
1203 /*
1204 * Check if AP+AP case, once primary AP chooses a DFS
1205 * channel secondary AP should always follow primary APs channel
1206 */
1207 if (!cds_concurrent_beaconing_sessions_running())
1208 return 0;
1209
1210 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1211 if (!con_sap_adapter)
1212 return 0;
1213
1214 sap_config = &adapter->sessionCtx.ap.sapConfig;
1215 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1216 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1217
1218 if (!CDS_IS_DFS_CH(con_ch))
1219 return 0;
1220
1221 hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"),
1222 sap_config->channel, con_ch);
1223 hddLog(LOG1, FL("Overriding guest AP's channel"));
1224 sap_config->channel = con_ch;
1225
1226 if (con_sap_config->acs_cfg.acs_mode == true) {
1227 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1228 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
1229 hddLog(LOGE, FL("Primary AP channel config error"));
1230 hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"),
1231 con_ch, con_sap_config->acs_cfg.pri_ch,
1232 con_sap_config->acs_cfg.ht_sec_ch);
1233 return -EINVAL;
1234 }
1235 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1236 * MCC restriction. So free ch list allocated in do_acs
1237 * func for Sec AP and realloc for Pri AP ch list size
1238 */
1239 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301240 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301242 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 &con_sap_config->acs_cfg,
1244 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301245 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 sizeof(uint8_t) *
1247 con_sap_config->acs_cfg.ch_list_count);
1248 if (!sap_config->acs_cfg.ch_list) {
1249 hddLog(LOGE, FL("ACS config alloc fail"));
1250 return -ENOMEM;
1251 }
1252
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301253 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 con_sap_config->acs_cfg.ch_list,
1255 con_sap_config->acs_cfg.ch_list_count);
1256
1257 } else {
1258 sap_config->acs_cfg.pri_ch = con_ch;
1259 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1260 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1261 }
1262
1263 return con_ch;
1264}
1265#else
1266int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1267{
1268 return 0;
1269}
1270#endif
1271
1272/**
1273 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1274 * @sap_cfg: pointer to SAP config struct
1275 *
1276 * This function sets the default ACS start and end channel for the given band
1277 * and also parses the given ACS channel list.
1278 *
1279 * Return: None
1280 */
1281
1282static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1283 bool vht_enabled)
1284{
1285 int i;
1286 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1287 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001288 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1289 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1291 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001292 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1293 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1295 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001296 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1297 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1299 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001300 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1301 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 }
1303
1304 if (ht_enabled)
1305 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1306
1307 if (vht_enabled)
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1309
1310
1311 /* Parse ACS Chan list from hostapd */
1312 if (!sap_cfg->acs_cfg.ch_list)
1313 return;
1314
1315 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1316 sap_cfg->acs_cfg.end_ch =
1317 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1318 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
1319 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i])
1320 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1321 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1322 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1323 }
1324}
1325
1326
1327static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1328
1329/**
1330 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1331 * @adapter: pointer to SAP adapter struct
1332 *
1333 * This function starts the ACS procedure if there are no
1334 * constraints like MBSSID DFS restrictions.
1335 *
1336 * Return: Status of ACS Start procedure
1337 */
1338
1339static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1340{
1341
1342 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1343 tsap_Config_t *sap_config;
1344 tpWLAN_SAPEventCB acs_event_callback;
1345 int status;
1346
1347 sap_config = &adapter->sessionCtx.ap.sapConfig;
1348 sap_config->channel = AUTO_CHANNEL_SELECT;
1349
1350 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1351 if (status < 0) {
1352 return status;
1353 } else {
1354 if (status > 0) {
1355 /*notify hostapd about channel override */
1356 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1357 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1358 return 0;
1359 }
1360 }
1361 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1362 if (status) {
1363 hddLog(LOGE, FL("ACS config failed"));
1364 return -EINVAL;
1365 }
1366
1367 acs_event_callback = hdd_hostapd_sap_event_cb;
1368
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301369 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301370 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex);
1372 status = wlansap_acs_chselect(
1373#ifdef WLAN_FEATURE_MBSSID
1374 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1375#else
1376 hdd_ctx->pcds_context,
1377#endif
1378 acs_event_callback, sap_config, adapter->dev);
1379
1380
1381 if (status) {
1382 hddLog(LOGE, FL("ACS channel select failed"));
1383 return -EINVAL;
1384 }
1385 sap_config->acs_cfg.acs_mode = true;
1386 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1387
1388 return 0;
1389}
1390
1391/**
1392 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1393 * @wiphy: Linux wiphy struct pointer
1394 * @wdev: Linux wireless device struct pointer
1395 * @data: ACS information from hostapd
1396 * @data_len: ACS information length
1397 *
1398 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1399 * and starts ACS procedure.
1400 *
1401 * Return: ACS procedure start status
1402 */
1403
1404static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1405 struct wireless_dev *wdev,
1406 const void *data, int data_len)
1407{
1408 struct net_device *ndev = wdev->netdev;
1409 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1410 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1411 tsap_Config_t *sap_config;
1412 struct sk_buff *temp_skbuff;
1413 int status = -EINVAL, i = 0;
1414 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1415 bool ht_enabled, ht40_enabled, vht_enabled;
1416 uint8_t ch_width;
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301417 uint8_t weight_list[MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418
1419 /* ***Note*** Donot set SME config related to ACS operation here because
1420 * ACS operation is not synchronouse and ACS for Second AP may come when
1421 * ACS operation for first AP is going on. So only do_acs is split to
1422 * seperate start_acs routine. Also SME-PMAC struct that is used to
1423 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1424 * config shall be set only from start_acs.
1425 */
1426
1427 /* nla_policy Policy template. Policy not applied as some attributes are
1428 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1429 *
1430 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1431 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1435 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1436 */
1437
Jeff Johnson1f61b612016-02-12 16:28:33 -08001438 ENTER_DEV(ndev);
1439
Anurag Chouhan6d760662016-02-20 16:05:43 +05301440 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 hdd_err("Command not allowed in FTM mode");
1442 return -EPERM;
1443 }
1444
1445 if (hdd_ctx->config->force_sap_acs) {
1446 hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled"));
1447 return -EPERM;
1448 }
1449
1450 status = wlan_hdd_validate_context(hdd_ctx);
1451 if (0 != status) {
1452 hddLog(LOGE, FL("HDD context is not valid"));
1453 goto out;
1454 }
1455 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301456 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457
1458 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1459 NULL);
1460 if (status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301461 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 goto out;
1463 }
1464
1465 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301466 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467 goto out;
1468 }
1469 sap_config->acs_cfg.hw_mode = nla_get_u8(
1470 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1471
1472 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1473 ht_enabled =
1474 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1475 else
1476 ht_enabled = 0;
1477
1478 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1479 ht40_enabled =
1480 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1481 else
1482 ht40_enabled = 0;
1483
1484 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1485 vht_enabled =
1486 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1487 else
1488 vht_enabled = 0;
1489
1490 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1491 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1492 } else {
1493 if (ht_enabled && ht40_enabled)
1494 ch_width = 40;
1495 else
1496 ch_width = 20;
1497 }
1498 if (ch_width == 80)
1499 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1500 else if (ch_width == 40)
1501 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1502 else
1503 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1504
1505 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1506 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1507 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1508 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1509 * since it contains the frequency values of the channels in
1510 * the channel list.
1511 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1512 * is present
1513 */
1514 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1515 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1516 sap_config->acs_cfg.ch_list_count = nla_len(
1517 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1518 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301519 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520 sizeof(uint8_t) *
1521 sap_config->acs_cfg.ch_list_count);
1522 if (sap_config->acs_cfg.ch_list == NULL)
1523 goto out;
1524
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301525 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001526 sap_config->acs_cfg.ch_list_count);
1527 }
1528 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1529 uint32_t *freq =
1530 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1531 sap_config->acs_cfg.ch_list_count = nla_len(
1532 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1533 sizeof(uint32_t);
1534 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301535 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536 sap_config->acs_cfg.ch_list_count);
1537 if (sap_config->acs_cfg.ch_list == NULL) {
1538 hddLog(LOGE, FL("ACS config alloc fail"));
1539 status = -ENOMEM;
1540 goto out;
1541 }
1542
1543 /* convert frequency to channel */
1544 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1545 sap_config->acs_cfg.ch_list[i] =
1546 ieee80211_frequency_to_channel(freq[i]);
1547 }
1548 }
1549
1550 hdd_debug("get pcl for DO_ACS vendor command");
1551
1552 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001553 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301554 sap_config->acs_cfg.pcl_channels,
1555 &sap_config->acs_cfg.pcl_ch_count,
1556 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301557 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 hddLog(LOGE, FL("Get PCL failed"));
1559
1560 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1561
1562 /* ACS override for android */
1563 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
1564 hddLog(LOG1, FL("ACS Config override for 11AC"));
1565 vht_enabled = 1;
1566 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1567 sap_config->acs_cfg.ch_width =
1568 hdd_ctx->config->vhtChannelWidth;
1569 /* No VHT80 in 2.4G so perform ACS accordingly */
1570 if (sap_config->acs_cfg.end_ch <= 14 &&
1571 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1572 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1573 }
1574
1575 hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"),
1576 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1577 ch_width, ht_enabled, vht_enabled,
1578 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1579
1580 if (sap_config->acs_cfg.ch_list_count) {
1581 hddLog(LOG1, FL("ACS channel list: len: %d"),
1582 sap_config->acs_cfg.ch_list_count);
1583 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1584 hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]);
1585 }
1586 sap_config->acs_cfg.acs_mode = true;
1587 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
1588 /* ***Note*** Completion variable usage is not allowed here since
1589 * ACS scan operation may take max 2.2 sec for 5G band.
1590 * 9 Active channel X 40 ms active scan time +
1591 * 16 Passive channel X 110ms passive scan time
1592 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1593 * for this long. So we split up the scanning part.
1594 */
1595 set_bit(ACS_PENDING, &adapter->event_flags);
1596 hddLog(LOG1, FL("ACS Pending for wlan%d"),
1597 adapter->dev->ifindex);
1598 status = 0;
1599 } else {
1600 status = wlan_hdd_cfg80211_start_acs(adapter);
1601 }
1602
1603out:
1604 if (0 == status) {
1605 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1606 NLMSG_HDRLEN);
1607 if (temp_skbuff != NULL)
1608 return cfg80211_vendor_cmd_reply(temp_skbuff);
1609 }
1610
1611 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1612
1613 return status;
1614}
1615
1616 /**
1617 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1618 * @wiphy: Linux wiphy struct pointer
1619 * @wdev: Linux wireless device struct pointer
1620 * @data: ACS information from hostapd
1621 * @data_len: ACS information len
1622 *
1623 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1624 * and starts ACS procedure.
1625 *
1626 * Return: ACS procedure start status
1627 */
1628
1629static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1630 struct wireless_dev *wdev,
1631 const void *data, int data_len)
1632{
1633 int ret;
1634
1635 cds_ssr_protect(__func__);
1636 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1637 cds_ssr_unprotect(__func__);
1638
1639 return ret;
1640}
1641
1642/**
1643 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1644 * @work: Linux workqueue struct pointer for ACS work
1645 *
1646 * This function starts the ACS procedure which was marked pending when an ACS
1647 * procedure was in progress for a concurrent SAP interface.
1648 *
1649 * Return: None
1650 */
1651
1652static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1653{
1654 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1655 acs_pending_work.work);
1656 wlan_hdd_cfg80211_start_acs(adapter);
1657}
1658
1659/**
1660 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1661 * @adapter: Pointer to SAP adapter struct
1662 * @pri_channel: SAP ACS procedure selected Primary channel
1663 * @sec_channel: SAP ACS procedure selected secondary channel
1664 *
1665 * This is a callback function from SAP module on ACS procedure is completed.
1666 * This function send the ACS selected channel information to hostapd
1667 *
1668 * Return: None
1669 */
1670
1671void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1672{
1673 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1674 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1675 struct sk_buff *vendor_event;
1676 int ret_val;
1677 hdd_adapter_t *con_sap_adapter;
1678 uint16_t ch_width;
1679
1680 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001681 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001682 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1683 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1684 GFP_KERNEL);
1685
1686 if (!vendor_event) {
1687 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
1688 return;
1689 }
1690
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001691 ret_val = nla_put_u8(vendor_event,
1692 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1693 sap_cfg->acs_cfg.pri_ch);
1694 if (ret_val) {
1695 hddLog(LOGE,
1696 FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail"));
1697 kfree_skb(vendor_event);
1698 return;
1699 }
1700
1701 ret_val = nla_put_u8(vendor_event,
1702 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1703 sap_cfg->acs_cfg.ht_sec_ch);
1704 if (ret_val) {
1705 hddLog(LOGE,
1706 FL(
1707 "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail"));
1708 kfree_skb(vendor_event);
1709 return;
1710 }
1711
1712 ret_val = nla_put_u8(vendor_event,
1713 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1714 sap_cfg->acs_cfg.vht_seg0_center_ch);
1715 if (ret_val) {
1716 hddLog(LOGE,
1717 FL(
1718 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail"));
1719 kfree_skb(vendor_event);
1720 return;
1721 }
1722
1723 ret_val = nla_put_u8(vendor_event,
1724 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1725 sap_cfg->acs_cfg.vht_seg1_center_ch);
1726 if (ret_val) {
1727 hddLog(LOGE,
1728 FL(
1729 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail"));
1730 kfree_skb(vendor_event);
1731 return;
1732 }
1733
1734 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1735 ch_width = 80;
1736 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1737 ch_width = 40;
1738 else
1739 ch_width = 20;
1740
1741 ret_val = nla_put_u16(vendor_event,
1742 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1743 ch_width);
1744 if (ret_val) {
1745 hddLog(LOGE,
1746 FL(
1747 "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail"));
1748 kfree_skb(vendor_event);
1749 return;
1750 }
1751 if (sap_cfg->acs_cfg.pri_ch > 14)
1752 ret_val = nla_put_u8(vendor_event,
1753 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1754 QCA_ACS_MODE_IEEE80211A);
1755 else
1756 ret_val = nla_put_u8(vendor_event,
1757 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1758 QCA_ACS_MODE_IEEE80211G);
1759
1760 if (ret_val) {
1761 hddLog(LOGE,
1762 FL(
1763 "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail"));
1764 kfree_skb(vendor_event);
1765 return;
1766 }
1767
1768 hddLog(LOG1,
1769 FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"),
1770 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1771 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1772 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1773
1774 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1775 /* ***Note*** As already mentioned Completion variable usage is not
1776 * allowed here since ACS scan operation may take max 2.2 sec.
1777 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1778 * operation.
1779 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1780 * when Primary AP ACS is complete and secondary AP ACS is started here
1781 * immediately, Primary AP start_bss may come inbetween ACS operation
1782 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1783 * delay. This path and below constraint will be removed on sessionizing
1784 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1785 * As per design constraint user space control application must take
1786 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1787 * this code path. Sec AP hostapd should be started after Primary AP
1788 * start beaconing which can be confirmed by getchannel iwpriv command
1789 */
1790
1791 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1792 if (con_sap_adapter &&
1793 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
1794#ifdef CONFIG_CNSS
1795 cnss_init_delayed_work(&con_sap_adapter->acs_pending_work,
1796 wlan_hdd_cfg80211_start_pending_acs);
1797#else
1798 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1799 wlan_hdd_cfg80211_start_pending_acs);
1800#endif
1801 /* Lets give 500ms for OBSS + START_BSS to complete */
1802 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1803 msecs_to_jiffies(500));
1804 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1805 }
1806
1807 return;
1808}
1809
1810static int
1811__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1812 struct wireless_dev *wdev,
1813 const void *data,
1814 int data_len)
1815{
1816 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1817 struct sk_buff *skb = NULL;
1818 uint32_t fset = 0;
1819 int ret;
1820
Jeff Johnson1f61b612016-02-12 16:28:33 -08001821 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301822
Anurag Chouhan6d760662016-02-20 16:05:43 +05301823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 hdd_err("Command not allowed in FTM mode");
1825 return -EPERM;
1826 }
1827
1828 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301829 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001830 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831
1832 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
1833 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
1834 fset |= WIFI_FEATURE_INFRA;
1835 }
1836 if (true == hdd_is_5g_supported(pHddCtx)) {
1837 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
1838 fset |= WIFI_FEATURE_INFRA_5G;
1839 }
1840#ifdef WLAN_FEATURE_P2P
1841 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1842 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
1843 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
1844 fset |= WIFI_FEATURE_P2P;
1845 }
1846#endif
1847 fset |= WIFI_FEATURE_SOFT_AP;
1848
1849 /* HOTSPOT is a supplicant feature, enable it by default */
1850 fset |= WIFI_FEATURE_HOTSPOT;
1851
1852#ifdef FEATURE_WLAN_EXTSCAN
1853 if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
1854 hddLog(LOG1, FL("EXTScan is supported by firmware"));
1855 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1856 }
1857#endif
1858 if (wlan_hdd_nan_is_supported()) {
1859 hddLog(LOG1, FL("NAN is supported by firmware"));
1860 fset |= WIFI_FEATURE_NAN;
1861 }
1862 if (sme_is_feature_supported_by_fw(RTT)) {
1863 hddLog(LOG1, FL("RTT is supported by firmware"));
1864 fset |= WIFI_FEATURE_D2D_RTT;
1865 fset |= WIFI_FEATURE_D2AP_RTT;
1866 }
1867#ifdef FEATURE_WLAN_SCAN_PNO
1868 if (pHddCtx->config->configPNOScanSupport &&
1869 sme_is_feature_supported_by_fw(PNO)) {
1870 hddLog(LOG1, FL("PNO is supported by firmware"));
1871 fset |= WIFI_FEATURE_PNO;
1872 }
1873#endif
1874 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1875#ifdef FEATURE_WLAN_TDLS
1876 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1877 sme_is_feature_supported_by_fw(TDLS)) {
1878 hddLog(LOG1, FL("TDLS is supported by firmware"));
1879 fset |= WIFI_FEATURE_TDLS;
1880 }
1881 if (sme_is_feature_supported_by_fw(TDLS) &&
1882 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1883 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
1884 hddLog(LOG1, FL("TDLS off-channel is supported by firmware"));
1885 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1886 }
1887#endif
1888#ifdef WLAN_AP_STA_CONCURRENCY
1889 fset |= WIFI_FEATURE_AP_STA;
1890#endif
1891 fset |= WIFI_FEATURE_RSSI_MONITOR;
1892
1893 if (hdd_link_layer_stats_supported())
1894 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1895
1896 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1897 NLMSG_HDRLEN);
1898 if (!skb) {
1899 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1900 return -EINVAL;
1901 }
1902 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
1903 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
1904 hddLog(LOGE, FL("nla put fail"));
1905 goto nla_put_failure;
1906 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301907 ret = cfg80211_vendor_cmd_reply(skb);
1908 EXIT();
1909 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910nla_put_failure:
1911 kfree_skb(skb);
1912 return -EINVAL;
1913}
1914
1915/**
1916 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1917 * @wiphy: pointer to wireless wiphy structure.
1918 * @wdev: pointer to wireless_dev structure.
1919 * @data: Pointer to the data to be passed via vendor interface
1920 * @data_len:Length of the data to be passed
1921 *
1922 * Return: Return the Success or Failure code.
1923 */
1924static int
1925wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1926 struct wireless_dev *wdev,
1927 const void *data, int data_len)
1928{
1929 int ret = 0;
1930
1931 cds_ssr_protect(__func__);
1932 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1933 data, data_len);
1934 cds_ssr_unprotect(__func__);
1935
1936 return ret;
1937}
1938
1939/**
1940 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1941 * @wiphy: pointer to wireless wiphy structure.
1942 * @wdev: pointer to wireless_dev structure.
1943 * @data: Pointer to the data to be passed via vendor interface
1944 * @data_len:Length of the data to be passed
1945 *
1946 * Set the MAC address that is to be used for scanning.
1947 *
1948 * Return: Return the Success or Failure code.
1949 */
1950static int
1951__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1952 struct wireless_dev *wdev,
1953 const void *data,
1954 int data_len)
1955{
1956 tpSirScanMacOui pReqMsg = NULL;
1957 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1958 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301959 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 int ret;
1961
Jeff Johnson1f61b612016-02-12 16:28:33 -08001962 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963
Anurag Chouhan6d760662016-02-20 16:05:43 +05301964 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 hdd_err("Command not allowed in FTM mode");
1966 return -EPERM;
1967 }
1968
1969 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301970 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972
1973 if (false == pHddCtx->config->enable_mac_spoofing) {
1974 hddLog(LOGW, FL("MAC address spoofing is not enabled"));
1975 return -ENOTSUPP;
1976 }
1977
1978 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1979 data, data_len, NULL)) {
1980 hddLog(LOGE, FL("Invalid ATTR"));
1981 return -EINVAL;
1982 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301983 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 if (!pReqMsg) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301985 hddLog(LOGE, FL("qdf_mem_malloc failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 return -ENOMEM;
1987 }
1988 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
1989 hddLog(LOGE, FL("attr mac oui failed"));
1990 goto fail;
1991 }
1992 nla_memcpy(&pReqMsg->oui[0],
1993 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1994 sizeof(pReqMsg->oui));
1995 hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0],
1996 pReqMsg->oui[1], pReqMsg->oui[2]);
1997 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301998 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301999 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 FL("sme_set_scanning_mac_oui failed(err=%d)"), status);
2001 goto fail;
2002 }
2003 return 0;
2004fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302005 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 return -EINVAL;
2007}
2008
2009/**
2010 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2011 * @wiphy: pointer to wireless wiphy structure.
2012 * @wdev: pointer to wireless_dev structure.
2013 * @data: Pointer to the data to be passed via vendor interface
2014 * @data_len:Length of the data to be passed
2015 *
2016 * Set the MAC address that is to be used for scanning. This is an
2017 * SSR-protecting wrapper function.
2018 *
2019 * Return: Return the Success or Failure code.
2020 */
2021static int
2022wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2023 struct wireless_dev *wdev,
2024 const void *data,
2025 int data_len)
2026{
2027 int ret;
2028
2029 cds_ssr_protect(__func__);
2030 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2031 data, data_len);
2032 cds_ssr_unprotect(__func__);
2033
2034 return ret;
2035}
2036
2037/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302038 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2039 * @wiphy: pointer phy adapter
2040 * @wdev: pointer to wireless device structure
2041 * @data: pointer to data buffer
2042 * @data_len: length of data
2043 *
2044 * This routine will give concurrency matrix
2045 *
2046 * Return: int status code
2047 */
2048static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2049 struct wireless_dev *wdev,
2050 const void *data,
2051 int data_len)
2052{
2053 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2054 uint8_t i, feature_sets, max_feature_sets;
2055 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2056 struct sk_buff *reply_skb;
2057 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2058 int ret;
2059
2060 ENTER_DEV(wdev->netdev);
2061
2062 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2063 hdd_err("Command not allowed in FTM mode");
2064 return -EPERM;
2065 }
2066
2067 ret = wlan_hdd_validate_context(hdd_ctx);
2068 if (0 != ret) {
2069 hdd_err("HDD context is not valid");
2070 return ret;
2071 }
2072
2073 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2074 data, data_len, NULL)) {
2075 hdd_err("Invalid ATTR");
2076 return -EINVAL;
2077 }
2078
2079 /* Parse and fetch max feature set */
2080 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2081 hdd_err("Attr max feature set size failed");
2082 return -EINVAL;
2083 }
2084 max_feature_sets = nla_get_u32(tb[
2085 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2086 hdd_info("Max feature set size: %d", max_feature_sets);
2087
2088 /* Fill feature combination matrix */
2089 feature_sets = 0;
2090 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2091 WIFI_FEATURE_P2P;
2092 /* Add more feature combinations here */
2093
2094 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2095 hdd_info("Number of feature sets:%d", feature_sets);
2096 hdd_info("Feature set matrix");
2097 for (i = 0; i < feature_sets; i++)
2098 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2099
2100 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2101 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2102 if (!reply_skb) {
2103 hdd_err("Feature set matrix: buffer alloc fail");
2104 return -ENOMEM;
2105 }
2106
2107 if (nla_put_u32(reply_skb,
2108 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2109 feature_sets) ||
2110 nla_put(reply_skb,
2111 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2112 sizeof(u32) * feature_sets,
2113 feature_set_matrix)) {
2114 hdd_err("nla put fail");
2115 kfree_skb(reply_skb);
2116 return -EINVAL;
2117 }
2118 return cfg80211_vendor_cmd_reply(reply_skb);
2119}
2120
2121/**
2122 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2123 * @wiphy: pointer to wireless wiphy structure.
2124 * @wdev: pointer to wireless_dev structure.
2125 * @data: Pointer to the data to be passed via vendor interface
2126 * @data_len:Length of the data to be passed
2127 *
2128 * Retrieves the concurrency feature set matrix
2129 *
2130 * Return: 0 on success, negative errno on failure
2131 */
2132static int
2133wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2134 struct wireless_dev *wdev,
2135 const void *data,
2136 int data_len)
2137{
2138 int ret;
2139
2140 cds_ssr_protect(__func__);
2141 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2142 data, data_len);
2143 cds_ssr_unprotect(__func__);
2144
2145 return ret;
2146}
2147
2148/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002149 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2150 * @feature_flags: pointer to the byte array of features.
2151 * @feature: Feature to be turned ON in the byte array.
2152 *
2153 * Return: None
2154 *
2155 * This is called to turn ON or SET the feature flag for the requested feature.
2156 **/
2157#define NUM_BITS_IN_BYTE 8
2158void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2159{
2160 uint32_t index;
2161 uint8_t bit_mask;
2162
2163 index = feature / NUM_BITS_IN_BYTE;
2164 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2165 feature_flags[index] |= bit_mask;
2166}
2167
2168/**
2169 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2170 * @wiphy: pointer to wireless wiphy structure.
2171 * @wdev: pointer to wireless_dev structure.
2172 * @data: Pointer to the data to be passed via vendor interface
2173 * @data_len:Length of the data to be passed
2174 *
2175 * This is called when wlan driver needs to send supported feature set to
2176 * supplicant upon a request/query from the supplicant.
2177 *
2178 * Return: Return the Success or Failure code.
2179 **/
2180#define MAX_CONCURRENT_CHAN_ON_24G 2
2181#define MAX_CONCURRENT_CHAN_ON_5G 2
2182static int
2183__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2184 struct wireless_dev *wdev,
2185 const void *data, int data_len)
2186{
2187 struct sk_buff *skb = NULL;
2188 uint32_t dbs_capability = 0;
2189 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302190 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 int ret_val;
2192
2193 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2194 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2195
Jeff Johnson1f61b612016-02-12 16:28:33 -08002196 ENTER_DEV(wdev->netdev);
2197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002198 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2199 if (ret_val)
2200 return ret_val;
2201
Anurag Chouhan6d760662016-02-20 16:05:43 +05302202 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 hdd_err("Command not allowed in FTM mode");
2204 return -EPERM;
2205 }
2206
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002207 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 hddLog(LOG1, FL("Key Mgmt Offload is supported"));
2209 wlan_hdd_cfg80211_set_feature(feature_flags,
2210 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2211 }
2212
2213 wlan_hdd_cfg80211_set_feature(feature_flags,
2214 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2215 if (wma_is_scan_simultaneous_capable())
2216 wlan_hdd_cfg80211_set_feature(feature_flags,
2217 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
2218 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2219 NLMSG_HDRLEN);
2220
2221 if (!skb) {
2222 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2223 return -ENOMEM;
2224 }
2225
2226 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2227 sizeof(feature_flags), feature_flags))
2228 goto nla_put_failure;
2229
2230 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302231 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 if (one_by_one_dbs)
2233 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2234
2235 if (two_by_two_dbs)
2236 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2237
2238 if (!one_by_one_dbs && !two_by_two_dbs)
2239 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2240 } else {
2241 hdd_err("wma_get_dbs_hw_mode failed");
2242 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2243 }
2244
2245 hdd_info("dbs_capability is %d", dbs_capability);
2246
2247 if (nla_put_u32(skb,
2248 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2249 MAX_CONCURRENT_CHAN_ON_24G))
2250 goto nla_put_failure;
2251
2252 if (nla_put_u32(skb,
2253 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2254 MAX_CONCURRENT_CHAN_ON_5G))
2255 goto nla_put_failure;
2256
2257 return cfg80211_vendor_cmd_reply(skb);
2258
2259nla_put_failure:
2260 kfree_skb(skb);
2261 return -EINVAL;
2262}
2263
2264/**
2265 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2266 * @wiphy: pointer to wireless wiphy structure.
2267 * @wdev: pointer to wireless_dev structure.
2268 * @data: Pointer to the data to be passed via vendor interface
2269 * @data_len:Length of the data to be passed
2270 *
2271 * This is called when wlan driver needs to send supported feature set to
2272 * supplicant upon a request/query from the supplicant.
2273 *
2274 * Return: Return the Success or Failure code.
2275 */
2276static int
2277wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2278 struct wireless_dev *wdev,
2279 const void *data, int data_len)
2280{
2281 int ret;
2282
2283 cds_ssr_protect(__func__);
2284 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2285 data, data_len);
2286 cds_ssr_unprotect(__func__);
2287
2288 return ret;
2289}
2290
2291
2292/**
2293 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2294 * @wiphy: The wiphy structure
2295 * @wdev: The wireless device
2296 * @data: Data passed by framework
2297 * @data_len: Parameters to be configured passed as data
2298 *
2299 * The roaming related parameters are configured by the framework
2300 * using this interface.
2301 *
2302 * Return: Return either success or failure code.
2303 */
2304static int
2305__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2306 struct wireless_dev *wdev, const void *data, int data_len)
2307{
2308 struct net_device *dev = wdev->netdev;
2309 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2310 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2311 uint8_t session_id;
2312 struct roam_ext_params roam_params;
2313 uint32_t cmd_type, req_id;
2314 struct nlattr *curr_attr;
2315 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2316 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2317 int rem, i;
2318 uint32_t buf_len = 0;
2319 int ret;
2320
Jeff Johnson1f61b612016-02-12 16:28:33 -08002321 ENTER_DEV(dev);
2322
Anurag Chouhan6d760662016-02-20 16:05:43 +05302323 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 hdd_err("Command not allowed in FTM mode");
2325 return -EPERM;
2326 }
2327
2328 ret = wlan_hdd_validate_context(pHddCtx);
2329 if (0 != ret) {
2330 hddLog(LOGE, FL("HDD context is not valid"));
2331 return -EINVAL;
2332 }
2333
2334 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2335 data, data_len,
2336 NULL)) {
2337 hddLog(LOGE, FL("Invalid ATTR"));
2338 return -EINVAL;
2339 }
2340 /* Parse and fetch Command Type*/
2341 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
2342 hddLog(LOGE, FL("roam cmd type failed"));
2343 goto fail;
2344 }
2345 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302346 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2348 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
2349 hddLog(LOGE, FL("attr request id failed"));
2350 goto fail;
2351 }
2352 req_id = nla_get_u32(
2353 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302354 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id);
2355 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 switch (cmd_type) {
2357 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2358 i = 0;
2359 nla_for_each_nested(curr_attr,
2360 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2361 rem) {
2362 if (nla_parse(tb2,
2363 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2364 nla_data(curr_attr), nla_len(curr_attr),
2365 NULL)) {
2366 hddLog(LOGE,
2367 FL("nla_parse failed"));
2368 goto fail;
2369 }
2370 /* Parse and Fetch allowed SSID list*/
2371 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
2372 hddLog(LOGE, FL("attr allowed ssid failed"));
2373 goto fail;
2374 }
2375 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2376 /*
2377 * Upper Layers include a null termination character.
2378 * Check for the actual permissible length of SSID and
2379 * also ensure not to copy the NULL termination
2380 * character to the driver buffer.
2381 */
2382 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2383 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2384 nla_memcpy(
2385 roam_params.ssid_allowed_list[i].ssId,
2386 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2387 buf_len - 1);
2388 roam_params.ssid_allowed_list[i].length =
2389 buf_len - 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302390 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391 FL("SSID[%d]: %.*s,length = %d"), i,
2392 roam_params.ssid_allowed_list[i].length,
2393 roam_params.ssid_allowed_list[i].ssId,
2394 roam_params.ssid_allowed_list[i].length);
2395 i++;
2396 } else {
2397 hddLog(LOGE, FL("Invalid buffer length"));
2398 }
2399 }
2400 roam_params.num_ssid_allowed_list = i;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302401 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002402 roam_params.num_ssid_allowed_list);
2403 sme_update_roam_params(pHddCtx->hHal, session_id,
2404 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2405 break;
2406 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2407 /* Parse and fetch 5G Boost Threshold */
2408 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
2409 hddLog(LOGE, FL("5G boost threshold failed"));
2410 goto fail;
2411 }
2412 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2413 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302414 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 roam_params.raise_rssi_thresh_5g);
2416 /* Parse and fetch 5G Penalty Threshold */
2417 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
2418 hddLog(LOGE, FL("5G penalty threshold failed"));
2419 goto fail;
2420 }
2421 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2422 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302423 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 roam_params.drop_rssi_thresh_5g);
2425 /* Parse and fetch 5G Boost Factor */
2426 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
2427 hddLog(LOGE, FL("5G boost Factor failed"));
2428 goto fail;
2429 }
2430 roam_params.raise_factor_5g = nla_get_u32(
2431 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302432 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 roam_params.raise_factor_5g);
2434 /* Parse and fetch 5G Penalty factor */
2435 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
2436 hddLog(LOGE, FL("5G Penalty Factor failed"));
2437 goto fail;
2438 }
2439 roam_params.drop_factor_5g = nla_get_u32(
2440 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302441 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 roam_params.drop_factor_5g);
2443 /* Parse and fetch 5G Max Boost */
2444 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
2445 hddLog(LOGE, FL("5G Max Boost failed"));
2446 goto fail;
2447 }
2448 roam_params.max_raise_rssi_5g = nla_get_u32(
2449 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302450 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 roam_params.max_raise_rssi_5g);
2452 /* Parse and fetch Rssi Diff */
2453 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
2454 hddLog(LOGE, FL("Rssi Diff failed"));
2455 goto fail;
2456 }
2457 roam_params.rssi_diff = nla_get_s32(
2458 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302459 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 roam_params.rssi_diff);
2461 /* Parse and fetch Alert Rssi Threshold */
2462 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
2463 hddLog(LOGE, FL("Alert Rssi Threshold failed"));
2464 goto fail;
2465 }
2466 roam_params.alert_rssi_threshold = nla_get_u32(
2467 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302468 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Alert RSSI Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 roam_params.alert_rssi_threshold);
2470 sme_update_roam_params(pHddCtx->hHal, session_id,
2471 roam_params,
2472 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2473 break;
2474 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2475 /* Parse and fetch Activate Good Rssi Roam */
2476 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
2477 hddLog(LOGE, FL("Activate Good Rssi Roam failed"));
2478 goto fail;
2479 }
2480 roam_params.good_rssi_roam = nla_get_s32(
2481 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302482 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Activate Good Rssi Roam (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 roam_params.good_rssi_roam);
2484 sme_update_roam_params(pHddCtx->hHal, session_id,
2485 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2486 break;
2487 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2488 /* Parse and fetch number of preferred BSSID */
2489 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
2490 hddLog(LOGE, FL("attr num of preferred bssid failed"));
2491 goto fail;
2492 }
2493 roam_params.num_bssid_favored = nla_get_u32(
2494 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302495 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Preferred BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 roam_params.num_bssid_favored);
2497 i = 0;
2498 nla_for_each_nested(curr_attr,
2499 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2500 rem) {
2501 if (nla_parse(tb2,
2502 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2503 nla_data(curr_attr), nla_len(curr_attr),
2504 NULL)) {
2505 hddLog(LOGE, FL("nla_parse failed"));
2506 goto fail;
2507 }
2508 /* Parse and fetch MAC address */
2509 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
2510 hddLog(LOGE, FL("attr mac address failed"));
2511 goto fail;
2512 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002513 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302515 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002516 hdd_debug(MAC_ADDRESS_STR,
2517 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002518 /* Parse and fetch preference factor*/
2519 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
2520 hddLog(LOGE, FL("BSSID Preference score failed"));
2521 goto fail;
2522 }
2523 roam_params.bssid_favored_factor[i] = nla_get_u32(
2524 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302525 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("BSSID Preference score (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 roam_params.bssid_favored_factor[i]);
2527 i++;
2528 }
2529 sme_update_roam_params(pHddCtx->hHal, session_id,
2530 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2531 break;
2532 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2533 /* Parse and fetch number of blacklist BSSID */
2534 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
2535 hddLog(LOGE, FL("attr num of blacklist bssid failed"));
2536 goto fail;
2537 }
2538 roam_params.num_bssid_avoid_list = nla_get_u32(
2539 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302540 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of blacklist BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 roam_params.num_bssid_avoid_list);
2542 i = 0;
2543 nla_for_each_nested(curr_attr,
2544 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2545 rem) {
2546 if (nla_parse(tb2,
2547 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2548 nla_data(curr_attr), nla_len(curr_attr),
2549 NULL)) {
2550 hddLog(LOGE, FL("nla_parse failed"));
2551 goto fail;
2552 }
2553 /* Parse and fetch MAC address */
2554 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
2555 hddLog(LOGE, FL("attr blacklist addr failed"));
2556 goto fail;
2557 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002558 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302560 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002561 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002563 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 i++;
2565 }
2566 sme_update_roam_params(pHddCtx->hHal, session_id,
2567 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2568 break;
2569 }
2570 return 0;
2571fail:
2572 return -EINVAL;
2573}
2574
2575/**
2576 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2577 * @wiphy: pointer to wireless wiphy structure.
2578 * @wdev: pointer to wireless_dev structure.
2579 * @data: Pointer to the data to be passed via vendor interface
2580 * @data_len:Length of the data to be passed
2581 *
2582 * Return: Return the Success or Failure code.
2583 */
2584static int
2585wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2586 struct wireless_dev *wdev,
2587 const void *data,
2588 int data_len)
2589{
2590 int ret;
2591
2592 cds_ssr_protect(__func__);
2593 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2594 data, data_len);
2595 cds_ssr_unprotect(__func__);
2596
2597 return ret;
2598}
2599
2600static const struct nla_policy
2601wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2602 +1] = {
2603 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2604};
2605
2606/**
2607 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2608 * @hdd_ctx: HDD context
2609 * @device_mode: device mode
2610 * Return: bool
2611 */
2612static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002613 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614{
2615 hdd_adapter_t *adapter;
2616 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2617 hdd_ap_ctx_t *ap_ctx;
2618 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302619 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302621 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002622 &adapter_node);
2623
2624 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302625 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 adapter = adapter_node->pAdapter;
2627
2628 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002629 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 ap_ctx =
2631 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2632
2633 /*
2634 * if there is SAP already running on DFS channel,
2635 * do not disable scan on dfs channels. Note that
2636 * with SAP on DFS, there cannot be conurrency on
2637 * single radio. But then we can have multiple
2638 * radios !!
2639 */
2640 if (CHANNEL_STATE_DFS ==
2641 cds_get_channel_state(
2642 ap_ctx->operatingChannel)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302643 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644 FL("SAP running on DFS channel"));
2645 return true;
2646 }
2647 }
2648
2649 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002650 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 sta_ctx =
2652 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2653
2654 /*
2655 * if STA is already connected on DFS channel,
2656 * do not disable scan on dfs channels
2657 */
2658 if (hdd_conn_is_connected(sta_ctx) &&
2659 (CHANNEL_STATE_DFS ==
2660 cds_get_channel_state(
2661 sta_ctx->conn_info.operationChannel))) {
2662 hddLog(LOGE,
2663 FL("client connected on DFS channel"));
2664 return true;
2665 }
2666 }
2667
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302668 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 adapter_node,
2670 &next);
2671 adapter_node = next;
2672 }
2673
2674 return false;
2675}
2676
2677/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002678 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2679 * @hdd_ctx: HDD context within host driver
2680 * @adapter: Adapter pointer
2681 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2682 *
2683 * Loops through devices to see who is operating on DFS channels
2684 * and then disables/enables DFS channels by calling SME API.
2685 * Fails the disable request if any device is active on a DFS channel.
2686 *
2687 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002689
2690int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2691 hdd_adapter_t *adapter,
2692 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002693{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002694 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302695 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697
2698 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2699 if (no_dfs_flag) {
2700 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002701 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702
2703 if (true == status)
2704 return -EOPNOTSUPP;
2705
2706 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002707 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708
2709 if (true == status)
2710 return -EOPNOTSUPP;
2711 }
2712
2713 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2714
2715 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2716
2717 /*
2718 * call the SME API to tunnel down the new channel list
2719 * to the firmware
2720 */
2721 status = sme_handle_dfs_chan_scan(
2722 h_hal, hdd_ctx->config->enableDFSChnlScan);
2723
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302724 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725 ret_val = 0;
2726
2727 /*
2728 * Clear the SME scan cache also. Note that the
2729 * clearing of scan results is independent of session;
2730 * so no need to iterate over
2731 * all sessions
2732 */
2733 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302734 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 ret_val = -EPERM;
2736 }
2737
2738 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302739 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 FL(" the DFS flag has not changed"));
2741 ret_val = 0;
2742 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002743 return ret_val;
2744}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002746/**
2747 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2748 * @wiphy: corestack handler
2749 * @wdev: wireless device
2750 * @data: data
2751 * @data_len: data length
2752 * Return: success(0) or reason code for failure
2753 */
2754static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2755 struct wireless_dev *wdev,
2756 const void *data,
2757 int data_len)
2758{
2759 struct net_device *dev = wdev->netdev;
2760 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2761 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2762 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2763 int ret_val;
2764 uint32_t no_dfs_flag = 0;
2765
Jeff Johnson1f61b612016-02-12 16:28:33 -08002766 ENTER_DEV(dev);
2767
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002768 ret_val = wlan_hdd_validate_context(hdd_ctx);
2769
2770 if (ret_val) {
2771 hdd_err("HDD context is not valid");
2772 return ret_val;
2773 }
2774
2775 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2776 data, data_len,
2777 wlan_hdd_set_no_dfs_flag_config_policy)) {
2778 hdd_err("invalid attr");
2779 return -EINVAL;
2780 }
2781
2782 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2783 hdd_err("attr dfs flag failed");
2784 return -EINVAL;
2785 }
2786
2787 no_dfs_flag = nla_get_u32(
2788 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2789
2790 hddLog(LOG1, FL(" DFS flag = %d"), no_dfs_flag);
2791
2792 if (no_dfs_flag > 1) {
2793 hddLog(LOGE, FL("invalid value of dfs flag"));
2794 return -EINVAL;
2795 }
2796
2797 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2798 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002799 return ret_val;
2800}
2801
2802/**
2803 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2804 *
2805 * @wiphy: wiphy device pointer
2806 * @wdev: wireless device pointer
2807 * @data: Vendof command data buffer
2808 * @data_len: Buffer length
2809 *
2810 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2811 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2812 *
2813 * Return: EOK or other error codes.
2814 */
2815
2816static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2817 struct wireless_dev *wdev,
2818 const void *data,
2819 int data_len)
2820{
2821 int ret;
2822
2823 cds_ssr_protect(__func__);
2824 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2825 data, data_len);
2826 cds_ssr_unprotect(__func__);
2827
2828 return ret;
2829}
2830
2831#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2832/**
2833 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2834 * @wiphy: pointer to wireless wiphy structure.
2835 * @wdev: pointer to wireless_dev structure.
2836 * @data: Pointer to the Key data
2837 * @data_len:Length of the data passed
2838 *
2839 * This is called when wlan driver needs to save the keys received via
2840 * vendor specific command.
2841 *
2842 * Return: Return the Success or Failure code.
2843 */
2844static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2845 struct wireless_dev *wdev,
2846 const void *data, int data_len)
2847{
2848 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
2849 struct net_device *dev = wdev->netdev;
2850 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
2851 hdd_context_t *hdd_ctx_ptr;
2852 int status;
2853
Jeff Johnson1f61b612016-02-12 16:28:33 -08002854 ENTER_DEV(dev);
2855
Anurag Chouhan6d760662016-02-20 16:05:43 +05302856 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 hdd_err("Command not allowed in FTM mode");
2858 return -EPERM;
2859 }
2860
2861 if ((data == NULL) || (data_len == 0) ||
2862 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
2863 hddLog(LOGE, FL("Invalid data"));
2864 return -EINVAL;
2865 }
2866
2867 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
2868 if (!hdd_ctx_ptr) {
2869 hddLog(LOGE, FL("HDD context is null"));
2870 return -EINVAL;
2871 }
2872
2873 status = wlan_hdd_validate_context(hdd_ctx_ptr);
2874 if (0 != status) {
2875 hddLog(LOGE, FL("HDD context is invalid"));
2876 return status;
2877 }
2878 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
2879 hdd_adapter_ptr->sessionId,
2880 true);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302881 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
2882 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
2884 hdd_adapter_ptr->sessionId, local_pmk, data_len);
2885 return 0;
2886}
2887
2888/**
2889 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2890 * @wiphy: pointer to wireless wiphy structure.
2891 * @wdev: pointer to wireless_dev structure.
2892 * @data: Pointer to the Key data
2893 * @data_len:Length of the data passed
2894 *
2895 * This is called when wlan driver needs to save the keys received via
2896 * vendor specific command.
2897 *
2898 * Return: Return the Success or Failure code.
2899 */
2900static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2901 struct wireless_dev *wdev,
2902 const void *data, int data_len)
2903{
2904 int ret;
2905
2906 cds_ssr_protect(__func__);
2907 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
2908 cds_ssr_unprotect(__func__);
2909
2910 return ret;
2911}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08002912#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913
2914static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
2915 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
2916 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
2917 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
2918};
2919
2920/**
2921 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2922 * @wiphy: pointer to wireless wiphy structure.
2923 * @wdev: pointer to wireless_dev structure.
2924 * @data: Pointer to the data to be passed via vendor interface
2925 * @data_len:Length of the data to be passed
2926 *
2927 * This is called when wlan driver needs to send wifi driver related info
2928 * (driver/fw version) to the user space application upon request.
2929 *
2930 * Return: Return the Success or Failure code.
2931 */
2932static int
2933__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2934 struct wireless_dev *wdev,
2935 const void *data, int data_len)
2936{
2937 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2938 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
2939 tSirVersionString version;
2940 uint32_t version_len;
2941 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
2942 uint8_t attr;
2943 int status;
2944 struct sk_buff *reply_skb = NULL;
2945
Jeff Johnson1f61b612016-02-12 16:28:33 -08002946 ENTER_DEV(wdev->netdev);
2947
Anurag Chouhan6d760662016-02-20 16:05:43 +05302948 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 hdd_err("Command not allowed in FTM mode");
2950 return -EPERM;
2951 }
2952
2953 status = wlan_hdd_validate_context(hdd_ctx);
2954 if (0 != status) {
2955 hddLog(LOGE, FL("HDD context is not valid"));
2956 return -EINVAL;
2957 }
2958
2959 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
2960 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
2961 hddLog(LOGE, FL("WIFI_INFO_GET NL CMD parsing failed"));
2962 return -EINVAL;
2963 }
2964
2965 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
2966 hddLog(LOG1, FL("Rcvd req for Driver version"));
2967 strlcpy(version, QWLAN_VERSIONSTR, sizeof(version));
2968 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
2969 } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
2970 hddLog(LOG1, FL("Rcvd req for FW version"));
2971 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
2972 &crmid);
2973 snprintf(version, sizeof(version), "%d:%d:%d:%d",
2974 major_spid, minor_spid, siid, crmid);
2975 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
2976 } else {
2977 hddLog(LOGE, FL("Invalid attribute in get wifi info request"));
2978 return -EINVAL;
2979 }
2980
2981 version_len = strlen(version);
2982 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2983 version_len + NLA_HDRLEN + NLMSG_HDRLEN);
2984 if (!reply_skb) {
2985 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2986 return -ENOMEM;
2987 }
2988
2989 if (nla_put(reply_skb, attr, version_len, version)) {
2990 hddLog(LOGE, FL("nla put fail"));
2991 kfree_skb(reply_skb);
2992 return -EINVAL;
2993 }
2994
2995 return cfg80211_vendor_cmd_reply(reply_skb);
2996}
2997
2998/**
2999 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3000 * @wiphy: pointer to wireless wiphy structure.
3001 * @wdev: pointer to wireless_dev structure.
3002 * @data: Pointer to the data to be passed via vendor interface
3003 * @data_len:Length of the data to be passed
3004 *
3005 * This is called when wlan driver needs to send wifi driver related info
3006 * (driver/fw version) to the user space application upon request.
3007 *
3008 * Return: Return the Success or Failure code.
3009 */
3010static int
3011wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3012 struct wireless_dev *wdev,
3013 const void *data, int data_len)
3014{
3015 int ret;
3016
3017 cds_ssr_protect(__func__);
3018 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3019 cds_ssr_unprotect(__func__);
3020
3021 return ret;
3022}
3023
3024/**
3025 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3026 * @wiphy: pointer to wireless wiphy structure.
3027 * @wdev: pointer to wireless_dev structure.
3028 * @data: Pointer to the data to be passed via vendor interface
3029 * @data_len:Length of the data to be passed
3030 *
3031 * This is called by userspace to know the supported logger features
3032 *
3033 * Return: Return the Success or Failure code.
3034 */
3035static int
3036__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3037 struct wireless_dev *wdev,
3038 const void *data, int data_len)
3039{
3040 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3041 int status;
3042 uint32_t features;
3043 struct sk_buff *reply_skb = NULL;
3044
Jeff Johnson1f61b612016-02-12 16:28:33 -08003045 ENTER_DEV(wdev->netdev);
3046
Anurag Chouhan6d760662016-02-20 16:05:43 +05303047 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 hdd_err("Command not allowed in FTM mode");
3049 return -EPERM;
3050 }
3051
3052 status = wlan_hdd_validate_context(hdd_ctx);
3053 if (0 != status) {
3054 hddLog(LOGE, FL("HDD context is not valid"));
3055 return -EINVAL;
3056 }
3057
3058 features = 0;
3059
3060 if (hdd_is_memdump_supported())
3061 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3062 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3063 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3064 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3065
3066 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3067 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3068 if (!reply_skb) {
3069 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3070 return -ENOMEM;
3071 }
3072
3073 hddLog(LOG1, FL("Supported logger features: 0x%0x"), features);
3074 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3075 features)) {
3076 hddLog(LOGE, FL("nla put fail"));
3077 kfree_skb(reply_skb);
3078 return -EINVAL;
3079 }
3080
3081 return cfg80211_vendor_cmd_reply(reply_skb);
3082}
3083
3084/**
3085 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3086 * @wiphy: pointer to wireless wiphy structure.
3087 * @wdev: pointer to wireless_dev structure.
3088 * @data: Pointer to the data to be passed via vendor interface
3089 * @data_len:Length of the data to be passed
3090 *
3091 * This is called by userspace to know the supported logger features
3092 *
3093 * Return: Return the Success or Failure code.
3094 */
3095static int
3096wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3097 struct wireless_dev *wdev,
3098 const void *data, int data_len)
3099{
3100 int ret;
3101
3102 cds_ssr_protect(__func__);
3103 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3104 data, data_len);
3105 cds_ssr_unprotect(__func__);
3106
3107 return ret;
3108}
3109
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003110#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111/**
3112 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3113 * @hdd_ctx_ptr: pointer to HDD Context.
3114 * @bssid: pointer to bssid of roamed AP.
3115 * @req_rsn_ie: Pointer to request RSN IE
3116 * @req_rsn_len: Length of the request RSN IE
3117 * @rsp_rsn_ie: Pointer to response RSN IE
3118 * @rsp_rsn_len: Length of the response RSN IE
3119 * @roam_info_ptr: Pointer to the roaming related information
3120 *
3121 * This is called when wlan driver needs to send the roaming and
3122 * authorization information after roaming.
3123 *
3124 * The information that would be sent is the request RSN IE, response
3125 * RSN IE and BSSID of the newly roamed AP.
3126 *
3127 * If the Authorized status is authenticated, then additional parameters
3128 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3129 * supplicant.
3130 *
3131 * The supplicant upon receiving this event would ignore the legacy
3132 * cfg80211_roamed call and use the entire information from this event.
3133 * The cfg80211_roamed should still co-exist since the kernel will
3134 * make use of the parameters even if the supplicant ignores it.
3135 *
3136 * Return: Return the Success or Failure code.
3137 */
3138int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3139 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3140 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3141{
3142 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003143 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 ENTER();
3145
3146 if (wlan_hdd_validate_context(hdd_ctx_ptr)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303147 hddLog(QDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid "));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 return -EINVAL;
3149 }
3150
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003151 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003152 !roam_info_ptr->roamSynchInProgress)
3153 return 0;
3154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3156 NULL,
3157 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3158 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3159 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003160 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3162 GFP_KERNEL);
3163
3164 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303165 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 FL("cfg80211_vendor_event_alloc failed"));
3167 return -EINVAL;
3168 }
3169
3170 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3171 ETH_ALEN, bssid) ||
3172 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3173 req_rsn_len, req_rsn_ie) ||
3174 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3175 rsp_rsn_len, rsp_rsn_ie)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303176 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003177 goto nla_put_failure;
3178 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303179 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 roam_info_ptr->synchAuthStatus);
3181 if (roam_info_ptr->synchAuthStatus ==
3182 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303183 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's"));
Naveen Rawat14298b92015-11-25 16:27:41 -08003184 if (nla_put_u8(skb,
3185 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3186 hdd_err("nla put fail");
3187 goto nla_put_failure;
3188 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003189 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3190 /* if FT or CCKM connection: dont send replay counter */
3191 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3192 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3193 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3194 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3195 nla_put(skb,
3196 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3197 SIR_REPLAY_CTR_LEN,
3198 roam_info_ptr->replay_ctr)) {
3199 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003200 hdd_err("failed to send replay counter.");
3201 goto nla_put_failure;
3202 }
3203 if (nla_put(skb,
3204 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3205 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3206 nla_put(skb,
3207 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3208 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3209 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 goto nla_put_failure;
3211 }
3212 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303213 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003214 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3215 false)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303216 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 goto nla_put_failure;
3218 }
3219 }
3220
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303221 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Subnet Change Status = %d"),
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003222 roam_info_ptr->subnet_change_status);
3223
3224 /*
3225 * Add subnet change status if subnet has changed
3226 * 0 = unchanged
3227 * 1 = changed
3228 * 2 = unknown
3229 */
3230 if (roam_info_ptr->subnet_change_status) {
3231 if (nla_put_u8(skb,
3232 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3233 roam_info_ptr->subnet_change_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303234 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003235 goto nla_put_failure;
3236 }
3237 }
3238
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 cfg80211_vendor_event(skb, GFP_KERNEL);
3240 return 0;
3241
3242nla_put_failure:
3243 kfree_skb(skb);
3244 return -EINVAL;
3245}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003246#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247
3248static const struct nla_policy
3249wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3250
3251 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3252 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3253 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3254};
3255
3256
3257/**
3258 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3259 * vendor command
3260 *
3261 * @wiphy: wiphy device pointer
3262 * @wdev: wireless device pointer
3263 * @data: Vendor command data buffer
3264 * @data_len: Buffer length
3265 *
3266 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3267 *
3268 * Return: Error code.
3269 */
3270static int
3271__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3272 struct wireless_dev *wdev,
3273 const void *data,
3274 int data_len)
3275{
3276 struct net_device *dev = wdev->netdev;
3277 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3278 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3279 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3280 int ret_val = 0;
3281 u32 modulated_dtim;
3282 u16 stats_avg_factor;
3283 u32 guard_time;
Krunal Sonie3531942016-04-12 17:43:53 -07003284 u32 ftm_capab;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303285 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286
Jeff Johnson1f61b612016-02-12 16:28:33 -08003287 ENTER_DEV(dev);
3288
Anurag Chouhan6d760662016-02-20 16:05:43 +05303289 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290 hdd_err("Command not allowed in FTM mode");
3291 return -EPERM;
3292 }
3293
3294 ret_val = wlan_hdd_validate_context(hdd_ctx);
3295 if (ret_val) {
3296 hddLog(LOGE, FL("HDD context is not valid"));
3297 return ret_val;
3298 }
3299
3300 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3301 data, data_len,
3302 wlan_hdd_wifi_config_policy)) {
3303 hddLog(LOGE, FL("invalid attr"));
3304 return -EINVAL;
3305 }
3306
Krunal Sonie3531942016-04-12 17:43:53 -07003307 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3308 ftm_capab = nla_get_u32(tb[
3309 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3310 hdd_ctx->config->fine_time_meas_cap =
3311 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3312 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
3313 hdd_ctx->config->fine_time_meas_cap);
3314 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3315 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3316 hdd_ctx->config->fine_time_meas_cap);
3317 }
3318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003319 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3320 modulated_dtim = nla_get_u32(
3321 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3322
3323 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3324 adapter->sessionId,
3325 modulated_dtim);
3326
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303327 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003328 ret_val = -EPERM;
3329 }
3330
3331 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3332 stats_avg_factor = nla_get_u16(
3333 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3334 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3335 adapter->sessionId,
3336 stats_avg_factor);
3337
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303338 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339 ret_val = -EPERM;
3340 }
3341
3342
3343 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3344 guard_time = nla_get_u32(
3345 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3346 status = sme_configure_guard_time(hdd_ctx->hHal,
3347 adapter->sessionId,
3348 guard_time);
3349
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303350 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 ret_val = -EPERM;
3352 }
3353
3354 return ret_val;
3355}
3356
3357/**
3358 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3359 * vendor command
3360 *
3361 * @wiphy: wiphy device pointer
3362 * @wdev: wireless device pointer
3363 * @data: Vendor command data buffer
3364 * @data_len: Buffer length
3365 *
3366 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3367 *
3368 * Return: EOK or other error codes.
3369 */
3370static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3371 struct wireless_dev *wdev,
3372 const void *data,
3373 int data_len)
3374{
3375 int ret;
3376
3377 cds_ssr_protect(__func__);
3378 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3379 data, data_len);
3380 cds_ssr_unprotect(__func__);
3381
3382 return ret;
3383}
3384
3385static const struct
3386nla_policy
3387qca_wlan_vendor_wifi_logger_start_policy
3388[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3389 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3390 = {.type = NLA_U32 },
3391 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3392 = {.type = NLA_U32 },
3393 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3394 = {.type = NLA_U32 },
3395};
3396
3397/**
3398 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3399 * or disable the collection of packet statistics from the firmware
3400 * @wiphy: WIPHY structure pointer
3401 * @wdev: Wireless device structure pointer
3402 * @data: Pointer to the data received
3403 * @data_len: Length of the data received
3404 *
3405 * This function enables or disables the collection of packet statistics from
3406 * the firmware
3407 *
3408 * Return: 0 on success and errno on failure
3409 */
3410static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3411 struct wireless_dev *wdev,
3412 const void *data,
3413 int data_len)
3414{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303415 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003416 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3417 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
3418 struct sir_wifi_start_log start_log;
3419
Jeff Johnson1f61b612016-02-12 16:28:33 -08003420 ENTER_DEV(wdev->netdev);
3421
Anurag Chouhan6d760662016-02-20 16:05:43 +05303422 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423 hdd_err("Command not allowed in FTM mode");
3424 return -EPERM;
3425 }
3426
3427 status = wlan_hdd_validate_context(hdd_ctx);
3428 if (0 != status) {
3429 hddLog(LOGE, FL("HDD context is not valid"));
3430 return -EINVAL;
3431 }
3432
3433 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
3434 data, data_len,
3435 qca_wlan_vendor_wifi_logger_start_policy)) {
3436 hddLog(LOGE, FL("Invalid attribute"));
3437 return -EINVAL;
3438 }
3439
3440 /* Parse and fetch ring id */
3441 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
3442 hddLog(LOGE, FL("attr ATTR failed"));
3443 return -EINVAL;
3444 }
3445 start_log.ring_id = nla_get_u32(
3446 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003447 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448
3449 /* Parse and fetch verbose level */
3450 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
3451 hddLog(LOGE, FL("attr verbose_level failed"));
3452 return -EINVAL;
3453 }
3454 start_log.verbose_level = nla_get_u32(
3455 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003456 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457
3458 /* Parse and fetch flag */
3459 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
3460 hddLog(LOGE, FL("attr flag failed"));
3461 return -EINVAL;
3462 }
3463 start_log.flag = nla_get_u32(
3464 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003465 hdd_info("flag=%d", start_log.flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003466
3467 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
3468
3469 if (start_log.ring_id == RING_ID_WAKELOCK) {
3470 /* Start/stop wakelock events */
3471 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
3472 cds_set_wakelock_logging(true);
3473 else
3474 cds_set_wakelock_logging(false);
3475 return 0;
3476 }
3477
3478 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303479 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"),
3481 status);
3482 return -EINVAL;
3483 }
3484 return 0;
3485}
3486
3487/**
3488 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
3489 * or disable the collection of packet statistics from the firmware
3490 * @wiphy: WIPHY structure pointer
3491 * @wdev: Wireless device structure pointer
3492 * @data: Pointer to the data received
3493 * @data_len: Length of the data received
3494 *
3495 * This function is used to enable or disable the collection of packet
3496 * statistics from the firmware
3497 *
3498 * Return: 0 on success and errno on failure
3499 */
3500static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3501 struct wireless_dev *wdev,
3502 const void *data,
3503 int data_len)
3504{
3505 int ret = 0;
3506
3507 cds_ssr_protect(__func__);
3508 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
3509 wdev, data, data_len);
3510 cds_ssr_unprotect(__func__);
3511
3512 return ret;
3513}
3514
3515static const struct
3516nla_policy
3517qca_wlan_vendor_wifi_logger_get_ring_data_policy
3518[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
3519 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
3520 = {.type = NLA_U32 },
3521};
3522
3523/**
3524 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
3525 * @wiphy: WIPHY structure pointer
3526 * @wdev: Wireless device structure pointer
3527 * @data: Pointer to the data received
3528 * @data_len: Length of the data received
3529 *
3530 * This function is used to flush or retrieve the per packet statistics from
3531 * the driver
3532 *
3533 * Return: 0 on success and errno on failure
3534 */
3535static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3536 struct wireless_dev *wdev,
3537 const void *data,
3538 int data_len)
3539{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303540 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 uint32_t ring_id;
3542 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3543 struct nlattr *tb
3544 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
3545
Jeff Johnson1f61b612016-02-12 16:28:33 -08003546 ENTER_DEV(wdev->netdev);
3547
Anurag Chouhan6d760662016-02-20 16:05:43 +05303548 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549 hdd_err("Command not allowed in FTM mode");
3550 return -EPERM;
3551 }
3552
3553 status = wlan_hdd_validate_context(hdd_ctx);
3554 if (0 != status) {
3555 hddLog(LOGE, FL("HDD context is not valid"));
3556 return -EINVAL;
3557 }
3558
3559 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
3560 data, data_len,
3561 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
3562 hddLog(LOGE, FL("Invalid attribute"));
3563 return -EINVAL;
3564 }
3565
3566 /* Parse and fetch ring id */
3567 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
3568 hddLog(LOGE, FL("attr ATTR failed"));
3569 return -EINVAL;
3570 }
3571
3572 ring_id = nla_get_u32(
3573 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
3574
3575 if (ring_id == RING_ID_PER_PACKET_STATS) {
3576 wlan_logging_set_per_pkt_stats();
3577 hddLog(LOG1, FL("Flushing/Retrieving packet stats"));
3578 }
3579
3580 hddLog(LOG1, FL("Bug report triggered by framework"));
3581
3582 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
3583 WLAN_LOG_INDICATOR_FRAMEWORK,
Abhishek Singh5ea86532016-04-27 14:10:53 +05303584 WLAN_LOG_REASON_CODE_UNUSED,
3585 true, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303586 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 hddLog(LOGE, FL("Failed to trigger bug report"));
3588 return -EINVAL;
3589 }
3590
3591 return 0;
3592}
3593
3594/**
3595 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
3596 * @wiphy: WIPHY structure pointer
3597 * @wdev: Wireless device structure pointer
3598 * @data: Pointer to the data received
3599 * @data_len: Length of the data received
3600 *
3601 * This function is used to flush or retrieve the per packet statistics from
3602 * the driver
3603 *
3604 * Return: 0 on success and errno on failure
3605 */
3606static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3607 struct wireless_dev *wdev,
3608 const void *data,
3609 int data_len)
3610{
3611 int ret = 0;
3612
3613 cds_ssr_protect(__func__);
3614 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
3615 wdev, data, data_len);
3616 cds_ssr_unprotect(__func__);
3617
3618 return ret;
3619}
3620
3621#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
3622/**
3623 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
3624 * @hdd_ctx: HDD context
3625 * @request_id: [input] request id
3626 * @pattern_id: [output] pattern id
3627 *
3628 * This function loops through request id to pattern id array
3629 * if the slot is available, store the request id and return pattern id
3630 * if entry exists, return the pattern id
3631 *
3632 * Return: 0 on success and errno on failure
3633 */
3634static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3635 uint32_t request_id,
3636 uint8_t *pattern_id)
3637{
3638 uint32_t i;
3639
3640 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3641 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3642 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
3643 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
3644 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3645 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3646 return 0;
3647 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
3648 request_id) {
3649 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3650 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3651 return 0;
3652 }
3653 }
3654 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3655 return -EINVAL;
3656}
3657
3658/**
3659 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
3660 * @hdd_ctx: HDD context
3661 * @request_id: [input] request id
3662 * @pattern_id: [output] pattern id
3663 *
3664 * This function loops through request id to pattern id array
3665 * reset request id to 0 (slot available again) and
3666 * return pattern id
3667 *
3668 * Return: 0 on success and errno on failure
3669 */
3670static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3671 uint32_t request_id,
3672 uint8_t *pattern_id)
3673{
3674 uint32_t i;
3675
3676 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3677 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3678 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
3679 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
3680 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3681 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3682 return 0;
3683 }
3684 }
3685 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3686 return -EINVAL;
3687}
3688
3689
3690/*
3691 * define short names for the global vendor params
3692 * used by __wlan_hdd_cfg80211_offloaded_packets()
3693 */
3694#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
3695#define PARAM_REQUEST_ID \
3696 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
3697#define PARAM_CONTROL \
3698 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
3699#define PARAM_IP_PACKET \
3700 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
3701#define PARAM_SRC_MAC_ADDR \
3702 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
3703#define PARAM_DST_MAC_ADDR \
3704 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
3705#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
3706
3707/**
3708 * wlan_hdd_add_tx_ptrn() - add tx pattern
3709 * @adapter: adapter pointer
3710 * @hdd_ctx: hdd context
3711 * @tb: nl attributes
3712 *
3713 * This function reads the NL attributes and forms a AddTxPtrn message
3714 * posts it to SME.
3715 *
3716 */
3717static int
3718wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3719 struct nlattr **tb)
3720{
3721 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303722 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723 uint32_t request_id, ret, len;
3724 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303725 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 uint16_t eth_type = htons(ETH_P_IP);
3727
3728 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3729 hddLog(LOGE, FL("Not in Connected state!"));
3730 return -ENOTSUPP;
3731 }
3732
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303733 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 if (!add_req) {
3735 hddLog(LOGE, FL("memory allocation failed"));
3736 return -ENOMEM;
3737 }
3738
3739 /* Parse and fetch request Id */
3740 if (!tb[PARAM_REQUEST_ID]) {
3741 hddLog(LOGE, FL("attr request id failed"));
3742 goto fail;
3743 }
3744
3745 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3746 if (request_id == MAX_REQUEST_ID) {
3747 hddLog(LOGE, FL("request_id cannot be MAX"));
3748 return -EINVAL;
3749 }
3750 hddLog(LOG1, FL("Request Id: %u"), request_id);
3751
3752 if (!tb[PARAM_PERIOD]) {
3753 hddLog(LOGE, FL("attr period failed"));
3754 goto fail;
3755 }
3756 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
3757 hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs);
3758 if (add_req->usPtrnIntervalMs == 0) {
3759 hddLog(LOGE, FL("Invalid interval zero, return failure"));
3760 goto fail;
3761 }
3762
3763 if (!tb[PARAM_SRC_MAC_ADDR]) {
3764 hddLog(LOGE, FL("attr source mac address failed"));
3765 goto fail;
3766 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08003767 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303768 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769 hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003770 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771
Anurag Chouhanc5548422016-02-24 18:33:27 +05303772 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003773 &adapter->macAddressCurrent)) {
3774 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 goto fail;
3776 }
3777
3778 if (!tb[PARAM_DST_MAC_ADDR]) {
3779 hddLog(LOGE, FL("attr dst mac address failed"));
3780 goto fail;
3781 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303782 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR,
3784 MAC_ADDR_ARRAY(dst_addr.bytes));
3785
3786 if (!tb[PARAM_IP_PACKET]) {
3787 hddLog(LOGE, FL("attr ip packet failed"));
3788 goto fail;
3789 }
3790 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
3791 hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize);
3792
3793 if (add_req->ucPtrnSize < 0 ||
3794 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
3795 ETH_HLEN)) {
3796 hddLog(LOGE, FL("Invalid IP packet len: %d"),
3797 add_req->ucPtrnSize);
3798 goto fail;
3799 }
3800
3801 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303802 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303803 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303804 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303805 QDF_MAC_ADDR_SIZE);
3806 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303807 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808 len += 2;
3809
3810 /*
3811 * This is the IP packet, add 14 bytes Ethernet (802.3) header
3812 * ------------------------------------------------------------
3813 * | 14 bytes Ethernet (802.3) header | IP header and payload |
3814 * ------------------------------------------------------------
3815 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303816 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 nla_data(tb[PARAM_IP_PACKET]),
3818 add_req->ucPtrnSize);
3819 add_req->ucPtrnSize += len;
3820
3821 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3822 if (ret) {
3823 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3824 goto fail;
3825 }
3826 add_req->ucPtrnId = pattern_id;
3827 hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId);
3828
3829 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303830 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 hddLog(LOGE,
3832 FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status);
3833 goto fail;
3834 }
3835
3836 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303837 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 return 0;
3839
3840fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303841 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842 return -EINVAL;
3843}
3844
3845/**
3846 * wlan_hdd_del_tx_ptrn() - delete tx pattern
3847 * @adapter: adapter pointer
3848 * @hdd_ctx: hdd context
3849 * @tb: nl attributes
3850 *
3851 * This function reads the NL attributes and forms a DelTxPtrn message
3852 * posts it to SME.
3853 *
3854 */
3855static int
3856wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3857 struct nlattr **tb)
3858{
3859 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303860 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003861 uint32_t request_id, ret;
3862 uint8_t pattern_id = 0;
3863
3864 /* Parse and fetch request Id */
3865 if (!tb[PARAM_REQUEST_ID]) {
3866 hddLog(LOGE, FL("attr request id failed"));
3867 return -EINVAL;
3868 }
3869 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3870 if (request_id == MAX_REQUEST_ID) {
3871 hddLog(LOGE, FL("request_id cannot be MAX"));
3872 return -EINVAL;
3873 }
3874
3875 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3876 if (ret) {
3877 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3878 return -EINVAL;
3879 }
3880
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303881 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 if (!del_req) {
3883 hddLog(LOGE, FL("memory allocation failed"));
3884 return -ENOMEM;
3885 }
3886
Anurag Chouhanc5548422016-02-24 18:33:27 +05303887 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08003888 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 del_req->ucPtrnId = pattern_id;
3890 hddLog(LOG1, FL("Request Id: %u Pattern id: %d"),
3891 request_id, del_req->ucPtrnId);
3892
3893 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303894 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 hddLog(LOGE,
3896 FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status);
3897 goto fail;
3898 }
3899
3900 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303901 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902 return 0;
3903
3904fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303905 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906 return -EINVAL;
3907}
3908
3909
3910/**
3911 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
3912 * @wiphy: Pointer to wireless phy
3913 * @wdev: Pointer to wireless device
3914 * @data: Pointer to data
3915 * @data_len: Data length
3916 *
3917 * Return: 0 on success, negative errno on failure
3918 */
3919static int
3920__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3921 struct wireless_dev *wdev,
3922 const void *data,
3923 int data_len)
3924{
3925 struct net_device *dev = wdev->netdev;
3926 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3927 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3928 struct nlattr *tb[PARAM_MAX + 1];
3929 uint8_t control;
3930 int ret;
3931 static const struct nla_policy policy[PARAM_MAX + 1] = {
3932 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3933 [PARAM_CONTROL] = { .type = NLA_U32 },
3934 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303935 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003936 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303937 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003938 [PARAM_PERIOD] = { .type = NLA_U32 },
3939 };
3940
Jeff Johnson1f61b612016-02-12 16:28:33 -08003941 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942
Anurag Chouhan6d760662016-02-20 16:05:43 +05303943 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 hdd_err("Command not allowed in FTM mode");
3945 return -EPERM;
3946 }
3947
3948 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303949 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951
3952 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
3953 hddLog(LOGE,
3954 FL("Periodic Tx Pattern Offload feature is not supported in FW!"));
3955 return -ENOTSUPP;
3956 }
3957
3958 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3959 hddLog(LOGE, FL("Invalid ATTR"));
3960 return -EINVAL;
3961 }
3962
3963 if (!tb[PARAM_CONTROL]) {
3964 hddLog(LOGE, FL("attr control failed"));
3965 return -EINVAL;
3966 }
3967 control = nla_get_u32(tb[PARAM_CONTROL]);
3968 hddLog(LOG1, FL("Control: %d"), control);
3969
3970 if (control == WLAN_START_OFFLOADED_PACKETS)
3971 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
3972 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
3973 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
3974 else {
3975 hddLog(LOGE, FL("Invalid control: %d"), control);
3976 return -EINVAL;
3977 }
3978}
3979
3980/*
3981 * done with short names for the global vendor params
3982 * used by __wlan_hdd_cfg80211_offloaded_packets()
3983 */
3984#undef PARAM_MAX
3985#undef PARAM_REQUEST_ID
3986#undef PARAM_CONTROL
3987#undef PARAM_IP_PACKET
3988#undef PARAM_SRC_MAC_ADDR
3989#undef PARAM_DST_MAC_ADDR
3990#undef PARAM_PERIOD
3991
3992/**
3993 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
3994 * @wiphy: wiphy structure pointer
3995 * @wdev: Wireless device structure pointer
3996 * @data: Pointer to the data received
3997 * @data_len: Length of @data
3998 *
3999 * Return: 0 on success; errno on failure
4000 */
4001static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4002 struct wireless_dev *wdev,
4003 const void *data,
4004 int data_len)
4005{
4006 int ret = 0;
4007
4008 cds_ssr_protect(__func__);
4009 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4010 wdev, data, data_len);
4011 cds_ssr_unprotect(__func__);
4012
4013 return ret;
4014}
4015#endif
4016
4017/*
4018 * define short names for the global vendor params
4019 * used by __wlan_hdd_cfg80211_monitor_rssi()
4020 */
4021#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4022#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4023#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4024#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4025#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4026
4027/**
4028 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4029 * @wiphy: Pointer to wireless phy
4030 * @wdev: Pointer to wireless device
4031 * @data: Pointer to data
4032 * @data_len: Data length
4033 *
4034 * Return: 0 on success, negative errno on failure
4035 */
4036static int
4037__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4038 struct wireless_dev *wdev,
4039 const void *data,
4040 int data_len)
4041{
4042 struct net_device *dev = wdev->netdev;
4043 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4044 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4045 struct nlattr *tb[PARAM_MAX + 1];
4046 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304047 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 int ret;
4049 uint32_t control;
4050 static const struct nla_policy policy[PARAM_MAX + 1] = {
4051 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4052 [PARAM_CONTROL] = { .type = NLA_U32 },
4053 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4054 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4055 };
4056
Jeff Johnson1f61b612016-02-12 16:28:33 -08004057 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004058
4059 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304060 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062
4063 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
4064 hddLog(LOGE, FL("Not in Connected state!"));
4065 return -ENOTSUPP;
4066 }
4067
4068 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
4069 hddLog(LOGE, FL("Invalid ATTR"));
4070 return -EINVAL;
4071 }
4072
4073 if (!tb[PARAM_REQUEST_ID]) {
4074 hddLog(LOGE, FL("attr request id failed"));
4075 return -EINVAL;
4076 }
4077
4078 if (!tb[PARAM_CONTROL]) {
4079 hddLog(LOGE, FL("attr control failed"));
4080 return -EINVAL;
4081 }
4082
4083 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4084 req.session_id = adapter->sessionId;
4085 control = nla_get_u32(tb[PARAM_CONTROL]);
4086
4087 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4088 req.control = true;
4089 if (!tb[PARAM_MIN_RSSI]) {
4090 hddLog(LOGE, FL("attr min rssi failed"));
4091 return -EINVAL;
4092 }
4093
4094 if (!tb[PARAM_MAX_RSSI]) {
4095 hddLog(LOGE, FL("attr max rssi failed"));
4096 return -EINVAL;
4097 }
4098
4099 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4100 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4101
4102 if (!(req.min_rssi < req.max_rssi)) {
4103 hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"),
4104 req.min_rssi, req.max_rssi);
4105 return -EINVAL;
4106 }
4107 hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"),
4108 req.min_rssi, req.max_rssi);
4109
4110 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4111 req.control = false;
4112 else {
4113 hddLog(LOGE, FL("Invalid control cmd: %d"), control);
4114 return -EINVAL;
4115 }
4116 hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"),
4117 req.request_id, req.session_id, req.control);
4118
4119 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304120 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 hddLog(LOGE,
4122 FL("sme_set_rssi_monitoring failed(err=%d)"), status);
4123 return -EINVAL;
4124 }
4125
4126 return 0;
4127}
4128
4129/*
4130 * done with short names for the global vendor params
4131 * used by __wlan_hdd_cfg80211_monitor_rssi()
4132 */
4133#undef PARAM_MAX
4134#undef PARAM_CONTROL
4135#undef PARAM_REQUEST_ID
4136#undef PARAM_MAX_RSSI
4137#undef PARAM_MIN_RSSI
4138
4139/**
4140 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4141 * @wiphy: wiphy structure pointer
4142 * @wdev: Wireless device structure pointer
4143 * @data: Pointer to the data received
4144 * @data_len: Length of @data
4145 *
4146 * Return: 0 on success; errno on failure
4147 */
4148static int
4149wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4150 const void *data, int data_len)
4151{
4152 int ret;
4153
4154 cds_ssr_protect(__func__);
4155 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4156 cds_ssr_unprotect(__func__);
4157
4158 return ret;
4159}
4160
4161/**
4162 * hdd_rssi_threshold_breached() - rssi breached NL event
4163 * @hddctx: HDD context
4164 * @data: rssi breached event data
4165 *
4166 * This function reads the rssi breached event %data and fill in the skb with
4167 * NL attributes and send up the NL event.
4168 *
4169 * Return: none
4170 */
4171void hdd_rssi_threshold_breached(void *hddctx,
4172 struct rssi_breach_event *data)
4173{
4174 hdd_context_t *hdd_ctx = hddctx;
4175 struct sk_buff *skb;
4176
4177 ENTER();
4178
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304179 if (wlan_hdd_validate_context(hdd_ctx))
4180 return;
4181 if (!data) {
4182 hddLog(LOGE, FL("data is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 return;
4184 }
4185
4186 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4187 NULL,
4188 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4189 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4190 GFP_KERNEL);
4191
4192 if (!skb) {
4193 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
4194 return;
4195 }
4196
4197 hddLog(LOG1, "Req Id: %u Current rssi: %d",
4198 data->request_id, data->curr_rssi);
4199 hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR,
4200 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4201
4202 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4203 data->request_id) ||
4204 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4205 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4206 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4207 data->curr_rssi)) {
4208 hddLog(LOGE, FL("nla put fail"));
4209 goto fail;
4210 }
4211
4212 cfg80211_vendor_event(skb, GFP_KERNEL);
4213 return;
4214
4215fail:
4216 kfree_skb(skb);
4217 return;
4218}
4219
4220/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
4221 * @wiphy: Pointer to wireless phy
4222 * @wdev: Pointer to wireless device
4223 * @data: Pointer to data
4224 * @data_len: Data length
4225 *
4226 * This function return the preferred frequency list generated by the policy
4227 * manager.
4228 *
4229 * Return: success or failure code
4230 */
4231static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4232 struct wireless_dev
4233 *wdev, const void *data,
4234 int data_len)
4235{
4236 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4237 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304238 QDF_STATUS status;
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05304239 uint8_t pcl[MAX_NUM_CHAN], weight_list[MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 uint32_t pcl_len = 0;
4241 uint32_t freq_list[MAX_NUM_CHAN];
4242 enum cds_con_mode intf_mode;
4243 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4244 struct sk_buff *reply_skb;
4245
Jeff Johnson1f61b612016-02-12 16:28:33 -08004246 ENTER_DEV(wdev->netdev);
4247
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 ret = wlan_hdd_validate_context(hdd_ctx);
4249 if (ret)
4250 return -EINVAL;
4251
4252 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4253 data, data_len, NULL)) {
4254 hdd_err("Invalid ATTR");
4255 return -EINVAL;
4256 }
4257
4258 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4259 hdd_err("attr interface type failed");
4260 return -EINVAL;
4261 }
4262
4263 intf_mode = nla_get_u32(tb
4264 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4265
4266 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4267 hdd_err("Invalid interface type");
4268 return -EINVAL;
4269 }
4270
4271 hdd_debug("Userspace requested pref freq list");
4272
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05304273 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
4274 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304275 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 hdd_err("Get pcl failed");
4277 return -EINVAL;
4278 }
4279
4280 /* convert channel number to frequency */
4281 for (i = 0; i < pcl_len; i++) {
4282 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4283 freq_list[i] =
4284 ieee80211_channel_to_frequency(pcl[i],
4285 IEEE80211_BAND_2GHZ);
4286 else
4287 freq_list[i] =
4288 ieee80211_channel_to_frequency(pcl[i],
4289 IEEE80211_BAND_5GHZ);
4290 }
4291
4292 /* send the freq_list back to supplicant */
4293 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4294 sizeof(u32) *
4295 pcl_len +
4296 NLMSG_HDRLEN);
4297
4298 if (!reply_skb) {
4299 hdd_err("Allocate reply_skb failed");
4300 return -EINVAL;
4301 }
4302
4303 if (nla_put_u32(reply_skb,
4304 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4305 intf_mode) ||
4306 nla_put(reply_skb,
4307 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4308 sizeof(uint32_t) * pcl_len,
4309 freq_list)) {
4310 hdd_err("nla put fail");
4311 kfree_skb(reply_skb);
4312 return -EINVAL;
4313 }
4314
4315 return cfg80211_vendor_cmd_reply(reply_skb);
4316}
4317
4318/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4319 * @wiphy: Pointer to wireless phy
4320 * @wdev: Pointer to wireless device
4321 * @data: Pointer to data
4322 * @data_len: Data length
4323 *
4324 * This function return the preferred frequency list generated by the policy
4325 * manager.
4326 *
4327 * Return: success or failure code
4328 */
4329static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4330 struct wireless_dev
4331 *wdev, const void *data,
4332 int data_len)
4333{
4334 int ret = 0;
4335
4336 cds_ssr_protect(__func__);
4337 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
4338 data, data_len);
4339 cds_ssr_unprotect(__func__);
4340
4341 return ret;
4342}
4343
4344/**
4345 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4346 * @wiphy: Pointer to wireless phy
4347 * @wdev: Pointer to wireless device
4348 * @data: Pointer to data
4349 * @data_len: Data length
4350 *
4351 * Return: 0 on success, negative errno on failure
4352 */
4353static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4354 struct wireless_dev *wdev,
4355 const void *data,
4356 int data_len)
4357{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304358 struct net_device *ndev = wdev->netdev;
4359 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4361 int ret = 0;
4362 enum cds_con_mode intf_mode;
4363 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4364 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365
Jeff Johnson1f61b612016-02-12 16:28:33 -08004366 ENTER_DEV(ndev);
4367
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 ret = wlan_hdd_validate_context(hdd_ctx);
4369 if (ret)
4370 return ret;
4371
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
4373 data, data_len, NULL)) {
4374 hdd_err("Invalid ATTR");
4375 return -EINVAL;
4376 }
4377
4378 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
4379 hdd_err("attr interface type failed");
4380 return -EINVAL;
4381 }
4382
4383 intf_mode = nla_get_u32(tb
4384 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
4385
4386 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4387 hdd_err("Invalid interface type");
4388 return -EINVAL;
4389 }
4390
4391 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
4392 hdd_err("attr probable freq failed");
4393 return -EINVAL;
4394 }
4395
4396 channel_hint = cds_freq_to_chan(nla_get_u32(tb
4397 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
4398
4399 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004400 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 channel_hint, HW_MODE_20_MHZ)) {
4402 hdd_err("Set channel hint failed due to concurrency check");
4403 return -EINVAL;
4404 }
4405
4406 if (hdd_ctx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304407 ret = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304408 if (!QDF_IS_STATUS_SUCCESS(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 hdd_err("clearing event failed");
4410
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304411 ret = cds_current_connections_update(adapter->sessionId,
4412 channel_hint,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05304413 SIR_UPDATE_REASON_SET_OPER_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304414 if (QDF_STATUS_E_FAILURE == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 /* return in the failure case */
4416 hdd_err("ERROR: connections update failed!!");
4417 return -EINVAL;
4418 }
4419
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304420 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421 /*
4422 * Success is the only case for which we expect hw mode
4423 * change to take place, hence we need to wait.
4424 * For any other return value it should be a pass
4425 * through
4426 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304427 ret = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304428 if (!QDF_IS_STATUS_SUCCESS(ret)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304429 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 return -EINVAL;
4431 }
4432
4433 }
4434 }
4435
4436 return 0;
4437}
4438
4439/**
4440 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4441 * @wiphy: Pointer to wireless phy
4442 * @wdev: Pointer to wireless device
4443 * @data: Pointer to data
4444 * @data_len: Data length
4445 *
4446 * Return: 0 on success, negative errno on failure
4447 */
4448static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4449 struct wireless_dev *wdev,
4450 const void *data,
4451 int data_len)
4452{
4453 int ret = 0;
4454
4455 cds_ssr_protect(__func__);
4456 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
4457 data, data_len);
4458 cds_ssr_unprotect(__func__);
4459
4460 return ret;
4461}
4462
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304463static const struct
4464nla_policy
4465qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
4466 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
4467};
4468
4469/**
4470 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
4471 * @wiphy: WIPHY structure pointer
4472 * @wdev: Wireless device structure pointer
4473 * @data: Pointer to the data received
4474 * @data_len: Length of the data received
4475 *
4476 * This function is used to get link properties like nss, rate flags and
4477 * operating frequency for the active connection with the given peer.
4478 *
4479 * Return: 0 on success and errno on failure
4480 */
4481static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4482 struct wireless_dev *wdev,
4483 const void *data,
4484 int data_len)
4485{
4486 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4487 struct net_device *dev = wdev->netdev;
4488 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4489 hdd_station_ctx_t *hdd_sta_ctx;
4490 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05304491 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304492 uint32_t sta_id;
4493 struct sk_buff *reply_skb;
4494 uint32_t rate_flags = 0;
4495 uint8_t nss;
4496 uint8_t final_rate_flags = 0;
4497 uint32_t freq;
4498
Jeff Johnson1f61b612016-02-12 16:28:33 -08004499 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304500
Anurag Chouhan6d760662016-02-20 16:05:43 +05304501 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304502 hdd_err("Command not allowed in FTM mode");
4503 return -EPERM;
4504 }
4505
4506 if (0 != wlan_hdd_validate_context(hdd_ctx))
4507 return -EINVAL;
4508
4509 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
4510 qca_wlan_vendor_attr_policy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304511 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid attribute"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304512 return -EINVAL;
4513 }
4514
4515 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304516 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304517 FL("Attribute peerMac not provided for mode=%d"),
4518 adapter->device_mode);
4519 return -EINVAL;
4520 }
4521
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304522 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05304523 QDF_MAC_ADDR_SIZE);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304524 hddLog(QDF_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304525 FL("peerMac="MAC_ADDRESS_STR" for device_mode:%d"),
4526 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
4527
Krunal Sonib4326f22016-03-10 13:05:51 -08004528 if (adapter->device_mode == QDF_STA_MODE ||
4529 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304530 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4531 if ((hdd_sta_ctx->conn_info.connState !=
4532 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304533 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304534 peer_mac, QDF_MAC_ADDR_SIZE)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304535 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304536 FL("Not Associated to mac "MAC_ADDRESS_STR),
4537 MAC_ADDR_ARRAY(peer_mac));
4538 return -EINVAL;
4539 }
4540
4541 nss = hdd_sta_ctx->conn_info.nss;
4542 freq = cds_chan_to_freq(
4543 hdd_sta_ctx->conn_info.operationChannel);
4544 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08004545 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
4546 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304547
4548 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
4549 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05304550 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304551 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304552 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304553 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304554 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304555 break;
4556 }
4557
4558 if (WLAN_MAX_STA_COUNT == sta_id) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304559 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304560 FL("No active peer with mac="MAC_ADDRESS_STR),
4561 MAC_ADDR_ARRAY(peer_mac));
4562 return -EINVAL;
4563 }
4564
4565 nss = adapter->aStaInfo[sta_id].nss;
4566 freq = cds_chan_to_freq(
4567 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
4568 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
4569 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304570 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304571 FL("Not Associated! with mac "MAC_ADDRESS_STR),
4572 MAC_ADDR_ARRAY(peer_mac));
4573 return -EINVAL;
4574 }
4575
4576 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
4577 if (rate_flags & eHAL_TX_RATE_VHT80) {
4578 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004579#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304580 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004581#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304582 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
4583 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004584#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304585 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004586#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304587 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
4588 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4589 } else if (rate_flags &
4590 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
4591 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004592#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304593 if (rate_flags & eHAL_TX_RATE_HT40)
4594 final_rate_flags |=
4595 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004596#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304597 }
4598
4599 if (rate_flags & eHAL_TX_RATE_SGI) {
4600 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
4601 final_rate_flags |= RATE_INFO_FLAGS_MCS;
4602 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
4603 }
4604 }
4605
4606 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4607 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
4608
4609 if (NULL == reply_skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304610 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304611 FL("getLinkProperties: skb alloc failed"));
4612 return -EINVAL;
4613 }
4614
4615 if (nla_put_u8(reply_skb,
4616 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
4617 nss) ||
4618 nla_put_u8(reply_skb,
4619 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
4620 final_rate_flags) ||
4621 nla_put_u32(reply_skb,
4622 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
4623 freq)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304624 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla_put failed"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304625 kfree_skb(reply_skb);
4626 return -EINVAL;
4627 }
4628
4629 return cfg80211_vendor_cmd_reply(reply_skb);
4630}
4631
4632/**
4633 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
4634 * properties.
4635 * @wiphy: WIPHY structure pointer
4636 * @wdev: Wireless device structure pointer
4637 * @data: Pointer to the data received
4638 * @data_len: Length of the data received
4639 *
4640 * This function is used to get link properties like nss, rate flags and
4641 * operating frequency for the active connection with the given peer.
4642 *
4643 * Return: 0 on success and errno on failure
4644 */
4645static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4646 struct wireless_dev *wdev,
4647 const void *data,
4648 int data_len)
4649{
4650 int ret = 0;
4651
4652 cds_ssr_protect(__func__);
4653 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
4654 wdev, data, data_len);
4655 cds_ssr_unprotect(__func__);
4656
4657 return ret;
4658}
4659
Peng Xu278d0122015-09-24 16:34:17 -07004660static const struct
4661nla_policy
4662qca_wlan_vendor_ota_test_policy
4663[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
4664 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
4665};
4666
4667/**
4668 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
4669 * @wiphy: Pointer to wireless phy
4670 * @wdev: Pointer to wireless device
4671 * @data: Pointer to data
4672 * @data_len: Data length
4673 *
4674 * Return: 0 on success, negative errno on failure
4675 */
4676static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4677 struct wireless_dev *wdev,
4678 const void *data,
4679 int data_len)
4680{
4681 struct net_device *dev = wdev->netdev;
4682 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4683 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
4684 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4685 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
4686 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304687 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07004688 uint32_t current_roam_state;
4689
Jeff Johnson1f61b612016-02-12 16:28:33 -08004690 ENTER_DEV(dev);
4691
Anurag Chouhan6d760662016-02-20 16:05:43 +05304692 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07004693 hdd_err("Command not allowed in FTM mode");
4694 return -EPERM;
4695 }
4696
4697 if (0 != wlan_hdd_validate_context(hdd_ctx))
4698 return -EINVAL;
4699
4700 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
4701 data, data_len,
4702 qca_wlan_vendor_ota_test_policy)) {
4703 hdd_err("invalid attr");
4704 return -EINVAL;
4705 }
4706
4707 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
4708 hdd_err("attr ota test failed");
4709 return -EINVAL;
4710 }
4711
4712 ota_enable = nla_get_u8(
4713 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
4714
4715 hdd_info(" OTA test enable = %d", ota_enable);
4716 if (ota_enable != 1) {
4717 hdd_err("Invalid value, only enable test mode is supported!");
4718 return -EINVAL;
4719 }
4720
4721 current_roam_state =
4722 sme_get_current_roam_state(hal, adapter->sessionId);
4723 status = sme_stop_roaming(hal, adapter->sessionId,
4724 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304725 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004726 hdd_err("Enable/Disable roaming failed");
4727 return -EINVAL;
4728 }
4729
4730 status = sme_ps_enable_disable(hal, adapter->sessionId,
4731 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304732 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004733 hdd_err("Enable/Disable power save failed");
4734 /* restore previous roaming setting */
4735 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
4736 current_roam_state == eCSR_ROAMING_STATE_JOINED)
4737 status = sme_start_roaming(hal, adapter->sessionId,
4738 eCsrHddIssued);
4739 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
4740 current_roam_state == eCSR_ROAMING_STATE_IDLE)
4741 status = sme_stop_roaming(hal, adapter->sessionId,
4742 eCsrHddIssued);
4743
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304744 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07004745 hdd_err("Restoring roaming state failed");
4746
4747 return -EINVAL;
4748 }
4749
4750
4751 return 0;
4752}
4753
4754/**
4755 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
4756 * @wiphy: Pointer to wireless phy
4757 * @wdev: Pointer to wireless device
4758 * @data: Pointer to data
4759 * @data_len: Data length
4760 *
4761 * Return: 0 on success, negative errno on failure
4762 */
4763static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4764 struct wireless_dev *wdev,
4765 const void *data,
4766 int data_len)
4767{
4768 int ret = 0;
4769
4770 cds_ssr_protect(__func__);
4771 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
4772 cds_ssr_unprotect(__func__);
4773
4774 return ret;
4775}
4776
Peng Xu4d67c8f2015-10-16 16:02:26 -07004777/**
4778 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4779 * @wiphy: Pointer to wireless phy
4780 * @wdev: Pointer to wireless device
4781 * @data: Pointer to data
4782 * @data_len: Data length
4783 *
4784 * Return: 0 on success, negative errno on failure
4785 */
4786static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4787 struct wireless_dev *wdev,
4788 const void *data,
4789 int data_len)
4790{
4791 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4792 struct net_device *dev = wdev->netdev;
4793 hdd_adapter_t *adapter = NULL;
4794 int ret = 0;
4795 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
4796 uint8_t scale_value;
4797
Jeff Johnson1f61b612016-02-12 16:28:33 -08004798 ENTER_DEV(dev);
4799
Peng Xu4d67c8f2015-10-16 16:02:26 -07004800 ret = wlan_hdd_validate_context(hdd_ctx);
4801 if (ret)
4802 return ret;
4803
4804 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4805
4806 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
4807 data, data_len, NULL)) {
4808 hdd_err("Invalid ATTR");
4809 return -EINVAL;
4810 }
4811
4812 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
4813 hdd_err("attr tx power scale failed");
4814 return -EINVAL;
4815 }
4816
4817 scale_value = nla_get_u8(tb
4818 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
4819
4820 if (scale_value > MAX_TXPOWER_SCALE) {
4821 hdd_err("Invalid tx power scale level");
4822 return -EINVAL;
4823 }
4824
4825 ret = wma_set_tx_power_scale(adapter->sessionId, scale_value);
4826
4827 if (ret != 0) {
4828 hdd_err("Set tx power scale failed");
4829 return -EINVAL;
4830 }
4831
4832 return 0;
4833}
4834
4835/**
4836 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4837 * @wiphy: Pointer to wireless phy
4838 * @wdev: Pointer to wireless device
4839 * @data: Pointer to data
4840 * @data_len: Data length
4841 *
4842 * Return: 0 on success, negative errno on failure
4843 */
4844static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4845 struct wireless_dev *wdev,
4846 const void *data,
4847 int data_len)
4848{
4849 int ret = 0;
4850
4851 cds_ssr_protect(__func__);
4852 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
4853 data, data_len);
4854 cds_ssr_unprotect(__func__);
4855
4856 return ret;
4857}
4858
4859/**
4860 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4861 * @wiphy: Pointer to wireless phy
4862 * @wdev: Pointer to wireless device
4863 * @data: Pointer to data
4864 * @data_len: Data length
4865 *
4866 * Return: 0 on success, negative errno on failure
4867 */
4868static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4869 struct wireless_dev *wdev,
4870 const void *data,
4871 int data_len)
4872{
4873 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4874 struct net_device *dev = wdev->netdev;
4875 hdd_adapter_t *adapter = NULL;
4876 int ret = 0;
4877 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
4878 uint8_t scale_value;
4879
Jeff Johnson1f61b612016-02-12 16:28:33 -08004880 ENTER_DEV(dev);
4881
Peng Xu4d67c8f2015-10-16 16:02:26 -07004882 ret = wlan_hdd_validate_context(hdd_ctx);
4883 if (ret)
4884 return ret;
4885
4886 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4887
4888 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
4889 data, data_len, NULL)) {
4890 hdd_err("Invalid ATTR");
4891 return -EINVAL;
4892 }
4893
4894 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
4895 hdd_err("attr tx power decrease db value failed");
4896 return -EINVAL;
4897 }
4898
4899 scale_value = nla_get_u8(tb
4900 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
4901
4902 ret = wma_set_tx_power_scale_decr_db(adapter->sessionId, scale_value);
4903
4904 if (ret != 0) {
4905 hdd_err("Set tx power decrease db failed");
4906 return -EINVAL;
4907 }
4908
4909 return 0;
4910}
4911
4912/**
4913 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4914 * @wiphy: Pointer to wireless phy
4915 * @wdev: Pointer to wireless device
4916 * @data: Pointer to data
4917 * @data_len: Data length
4918 *
4919 * Return: 0 on success, negative errno on failure
4920 */
4921static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4922 struct wireless_dev *wdev,
4923 const void *data,
4924 int data_len)
4925{
4926 int ret = 0;
4927
4928 cds_ssr_protect(__func__);
4929 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
4930 data, data_len);
4931 cds_ssr_unprotect(__func__);
4932
4933 return ret;
4934}
Arun Khandavalli2476ef52016-04-26 20:19:43 +05304935/*
4936 * define short names for the global vendor params
4937 * used by __wlan_hdd_cfg80211_bpf_offload()
4938 */
4939#define BPF_INVALID \
4940 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
4941#define BPF_SET_RESET \
4942 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
4943#define BPF_VERSION \
4944 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
4945#define BPF_FILTER_ID \
4946 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
4947#define BPF_PACKET_SIZE \
4948 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
4949#define BPF_CURRENT_OFFSET \
4950 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
4951#define BPF_PROGRAM \
4952 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
4953#define BPF_MAX \
4954 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07004955
Arun Khandavalli2476ef52016-04-26 20:19:43 +05304956static const struct nla_policy
4957wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
4958 [BPF_SET_RESET] = {.type = NLA_U32},
4959 [BPF_VERSION] = {.type = NLA_U32},
4960 [BPF_FILTER_ID] = {.type = NLA_U32},
4961 [BPF_PACKET_SIZE] = {.type = NLA_U32},
4962 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
4963 [BPF_PROGRAM] = {.type = NLA_U8},
4964};
4965
4966/**
4967 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
4968 * @hdd_context: hdd_context
4969 * @bpf_get_offload: struct for get offload
4970 *
4971 * This function receives the response/data from the lower layer and
4972 * checks to see if the thread is still waiting then post the results to
4973 * upper layer, if the request has timed out then ignore.
4974 *
4975 * Return: None
4976 */
4977void hdd_get_bpf_offload_cb(void *hdd_context,
4978 struct sir_bpf_get_offload *data)
4979{
4980 hdd_context_t *hdd_ctx = hdd_context;
4981 struct hdd_bpf_context *context;
4982
4983 ENTER();
4984
4985 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
4986 hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"),
4987 data);
4988 return;
4989 }
4990
4991 spin_lock(&hdd_context_lock);
4992
4993 context = &bpf_context;
4994 /* The caller presumably timed out so there is nothing we can do */
4995 if (context->magic != BPF_CONTEXT_MAGIC) {
4996 spin_unlock(&hdd_context_lock);
4997 return;
4998 }
4999
5000 /* context is valid so caller is still waiting */
5001 /* paranoia: invalidate the magic */
5002 context->magic = 0;
5003
5004 context->capability_response = *data;
5005 complete(&context->completion);
5006
5007 spin_unlock(&hdd_context_lock);
5008
5009 return;
5010}
5011
5012/**
5013 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
5014 * @hdd_context: hdd_context
5015 * @bpf_get_offload: struct for get offload
5016 *
5017 * Return: 0 on success, error number otherwise.
5018 */
5019static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
5020 struct sir_bpf_get_offload *bpf_get_offload)
5021{
5022 struct sk_buff *skb;
5023 uint32_t nl_buf_len;
5024
5025 ENTER();
5026
5027 nl_buf_len = NLMSG_HDRLEN;
5028 nl_buf_len +=
5029 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
5030 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
5031
5032 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
5033 if (!skb) {
5034 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
5035 return -ENOMEM;
5036 }
5037
5038 hddLog(LOG1, "BPF Version: %u BPF max bytes: %u",
5039 bpf_get_offload->bpf_version,
5040 bpf_get_offload->max_bytes_for_bpf_inst);
5041
5042 if (nla_put_u32(skb, BPF_PACKET_SIZE,
5043 bpf_get_offload->max_bytes_for_bpf_inst) ||
5044 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
5045 hddLog(LOGE, FL("nla put failure"));
5046 goto nla_put_failure;
5047 }
5048
5049 cfg80211_vendor_cmd_reply(skb);
5050 EXIT();
5051 return 0;
5052
5053nla_put_failure:
5054 kfree_skb(skb);
5055 return -EINVAL;
5056}
5057
5058/**
5059 * hdd_get_bpf_offload - Get BPF offload Capabilities
5060 * @hdd_ctx: Hdd context
5061 *
5062 * Return: 0 on success, errno on failure
5063 */
5064static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
5065{
5066 unsigned long rc;
5067 struct hdd_bpf_context *context;
5068 QDF_STATUS status;
5069 int ret;
5070
5071 ENTER();
5072
5073 spin_lock(&hdd_context_lock);
5074 context = &bpf_context;
5075 context->magic = BPF_CONTEXT_MAGIC;
5076 INIT_COMPLETION(context->completion);
5077 spin_unlock(&hdd_context_lock);
5078
5079 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
5080 if (!QDF_IS_STATUS_SUCCESS(status)) {
5081 hddLog(LOGE, FL("Unable to retrieve BPF caps"));
5082 return -EINVAL;
5083 }
5084 /* request was sent -- wait for the response */
5085 rc = wait_for_completion_timeout(&context->completion,
5086 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
5087 if (!rc) {
5088 hddLog(LOGE, FL("Target response timed out"));
5089 spin_lock(&hdd_context_lock);
5090 context->magic = 0;
5091 spin_unlock(&hdd_context_lock);
5092
5093 return -ETIMEDOUT;
5094 }
5095 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
5096 &bpf_context.capability_response);
5097 if (ret)
5098 hddLog(LOGE, FL("Failed to post get bpf capabilities"));
5099
5100 EXIT();
5101 return ret;
5102}
5103
5104/**
5105 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
5106 * @hdd_ctx: Hdd context
5107 * @tb: Length of @data
5108 * @session_id: Session identifier
5109 *
5110 * Return: 0 on success; errno on failure
5111 */
5112static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
5113 struct nlattr **tb,
5114 uint8_t session_id)
5115{
5116 struct sir_bpf_set_offload *bpf_set_offload;
5117 QDF_STATUS status;
5118 int prog_len;
5119
5120 ENTER();
5121
5122 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
5123 if (bpf_set_offload == NULL) {
5124 hddLog(LOGE, FL("qdf_mem_malloc failed for bpf_set_offload"));
5125 return -ENOMEM;
5126 }
5127 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
5128
5129 /* Parse and fetch bpf packet size */
5130 if (!tb[BPF_PACKET_SIZE]) {
5131 hddLog(LOGE, FL("attr bpf packet size failed"));
5132 goto fail;
5133 }
5134 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
5135
5136 if (!bpf_set_offload->total_length) {
5137 hddLog(LOG1, FL("BPF reset packet filter received"));
5138 goto post_sme;
5139 }
5140
5141 /* Parse and fetch bpf program */
5142 if (!tb[BPF_PROGRAM]) {
5143 hddLog(LOGE, FL("attr bpf program failed"));
5144 goto fail;
5145 }
5146
5147 prog_len = nla_len(tb[BPF_PROGRAM]);
5148 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
5149 bpf_set_offload->current_length = prog_len;
5150 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
5151 bpf_set_offload->session_id = session_id;
5152
5153 /* Parse and fetch filter Id */
5154 if (!tb[BPF_FILTER_ID]) {
5155 hddLog(LOGE, FL("attr filter id failed"));
5156 goto fail;
5157 }
5158 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
5159
5160 /* Parse and fetch current offset */
5161 if (!tb[BPF_CURRENT_OFFSET]) {
5162 hddLog(LOGE, FL("attr current offset failed"));
5163 goto fail;
5164 }
5165 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
5166
5167post_sme:
5168 hddLog(LOG1, FL("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d"),
5169 bpf_set_offload->session_id,
5170 bpf_set_offload->version,
5171 bpf_set_offload->filter_id,
5172 bpf_set_offload->total_length,
5173 bpf_set_offload->current_length,
5174 bpf_set_offload->current_offset);
5175
5176 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
5177 if (!QDF_IS_STATUS_SUCCESS(status)) {
5178 hddLog(LOGE,
5179 FL("sme_set_bpf_instructions failed(err=%d)"), status);
5180 goto fail;
5181 }
5182 EXIT();
5183 if (bpf_set_offload->current_length)
5184 qdf_mem_free(bpf_set_offload->program);
5185 qdf_mem_free(bpf_set_offload);
5186 return 0;
5187
5188fail:
5189 if (bpf_set_offload->current_length)
5190 qdf_mem_free(bpf_set_offload->program);
5191 qdf_mem_free(bpf_set_offload);
5192 return -EINVAL;
5193}
5194
5195/**
5196 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
5197 * @wiphy: wiphy structure pointer
5198 * @wdev: Wireless device structure pointer
5199 * @data: Pointer to the data received
5200 * @data_len: Length of @data
5201 *
5202 * Return: 0 on success; errno on failure
5203 */
5204static int
5205__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
5206 struct wireless_dev *wdev,
5207 const void *data, int data_len)
5208{
5209 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5210 struct net_device *dev = wdev->netdev;
5211 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5212 struct nlattr *tb[BPF_MAX + 1];
5213 int ret_val, packet_filter_subcmd;
5214
5215 ENTER();
5216
5217 ret_val = wlan_hdd_validate_context(hdd_ctx);
5218 if (ret_val)
5219 return ret_val;
5220
5221 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5222 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5223 return -EINVAL;
5224 }
5225
5226 if (!hdd_ctx->bpf_enabled) {
5227 hddLog(LOGE, FL("BPF offload is not supported by firmware"));
5228 return -ENOTSUPP;
5229 }
5230
5231 if (nla_parse(tb, BPF_MAX, data, data_len,
5232 wlan_hdd_bpf_offload_policy)) {
5233 hddLog(LOGE, FL("Invalid ATTR"));
5234 return -EINVAL;
5235 }
5236
5237 if (!tb[BPF_SET_RESET]) {
5238 hddLog(LOGE, FL("attr bpf set reset failed"));
5239 return -EINVAL;
5240 }
5241
5242 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
5243
5244 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
5245 return hdd_get_bpf_offload(hdd_ctx);
5246 else
5247 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
5248 pAdapter->sessionId);
5249}
5250
5251/**
5252 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
5253 * @wiphy: wiphy structure pointer
5254 * @wdev: Wireless device structure pointer
5255 * @data: Pointer to the data received
5256 * @data_len: Length of @data
5257 *
5258 * Return: 0 on success; errno on failure
5259 */
5260
5261static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
5262 struct wireless_dev *wdev,
5263 const void *data, int data_len)
5264{
5265 int ret;
5266
5267 cds_ssr_protect(__func__);
5268 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
5269 cds_ssr_unprotect(__func__);
5270
5271 return ret;
5272}
5273
5274/**
5275 * hdd_init_bpf_completion() - Initialize the completion event for bpf
5276 *
5277 * Return: None
5278 */
5279void hdd_init_bpf_completion(void)
5280{
5281 init_completion(&bpf_context.completion);
5282}
5283
5284#undef BPF_INVALID
5285#undef BPF_SET_RESET
5286#undef BPF_VERSION
5287#undef BPF_ID
5288#undef BPF_PACKET_SIZE
5289#undef BPF_CURRENT_OFFSET
5290#undef BPF_PROGRAM
5291#undef BPF_MAX
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
5293 {
5294 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5295 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
5296 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5297 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5298 .doit = is_driver_dfs_capable
5299 },
5300
5301#ifdef WLAN_FEATURE_NAN
5302 {
5303 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5304 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
5305 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5306 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5307 .doit = wlan_hdd_cfg80211_nan_request
5308 },
5309#endif
5310
5311#ifdef WLAN_FEATURE_STATS_EXT
5312 {
5313 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5314 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
5315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5316 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5317 .doit = wlan_hdd_cfg80211_stats_ext_request
5318 },
5319#endif
5320#ifdef FEATURE_WLAN_EXTSCAN
5321 {
5322 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5323 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
5324 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5325 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5326 .doit = wlan_hdd_cfg80211_extscan_start
5327 },
5328 {
5329 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5330 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
5331 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5332 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5333 .doit = wlan_hdd_cfg80211_extscan_stop
5334 },
5335 {
5336 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5337 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
5338 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5339 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
5340 },
5341 {
5342 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5343 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
5344 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5345 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5346 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
5347 },
5348 {
5349 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5350 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
5351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5352 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5353 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
5354 },
5355 {
5356 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5357 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
5358 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5359 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5360 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
5361 },
5362 {
5363 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5364 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
5365 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5366 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5367 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
5368 },
5369 {
5370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5371 .info.subcmd =
5372 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
5373 .flags =
5374 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
5375 WIPHY_VENDOR_CMD_NEED_RUNNING,
5376 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
5377 },
5378 {
5379 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5380 .info.subcmd =
5381 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
5382 .flags =
5383 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
5384 WIPHY_VENDOR_CMD_NEED_RUNNING,
5385 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
5386 },
5387 {
5388 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5389 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
5390 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5391 WIPHY_VENDOR_CMD_NEED_NETDEV |
5392 WIPHY_VENDOR_CMD_NEED_RUNNING,
5393 .doit = wlan_hdd_cfg80211_set_epno_list
5394 },
5395#endif /* FEATURE_WLAN_EXTSCAN */
5396
5397#ifdef WLAN_FEATURE_LINK_LAYER_STATS
5398 {
5399 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5400 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
5401 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5402 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5403 .doit = wlan_hdd_cfg80211_ll_stats_clear
5404 },
5405
5406 {
5407 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5408 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
5409 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5410 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5411 .doit = wlan_hdd_cfg80211_ll_stats_set
5412 },
5413
5414 {
5415 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5416 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
5417 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5418 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5419 .doit = wlan_hdd_cfg80211_ll_stats_get
5420 },
5421#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
5422#ifdef FEATURE_WLAN_TDLS
5423 {
5424 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5425 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
5426 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5427 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5428 .doit = wlan_hdd_cfg80211_exttdls_enable
5429 },
5430 {
5431 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5432 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
5433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5434 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5435 .doit = wlan_hdd_cfg80211_exttdls_disable
5436 },
5437 {
5438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
5440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5441 .doit = wlan_hdd_cfg80211_exttdls_get_status
5442 },
5443#endif
5444 {
5445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
5447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5448 .doit = wlan_hdd_cfg80211_get_supported_features
5449 },
5450 {
5451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
5453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5454 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
5455 },
5456 {
5457 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5458 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
5459 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05305460 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461 },
5462 {
5463 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5464 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
5465 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5466 WIPHY_VENDOR_CMD_NEED_NETDEV,
5467 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
5468 },
5469
5470 {
5471 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5472 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
5473 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5474 WIPHY_VENDOR_CMD_NEED_NETDEV |
5475 WIPHY_VENDOR_CMD_NEED_RUNNING,
5476 .doit = wlan_hdd_cfg80211_do_acs
5477 },
5478
5479 {
5480 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5481 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
5482 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5483 WIPHY_VENDOR_CMD_NEED_NETDEV,
5484 .doit = wlan_hdd_cfg80211_get_features
5485 },
5486#ifdef WLAN_FEATURE_ROAM_OFFLOAD
5487 {
5488 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5489 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
5490 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5491 WIPHY_VENDOR_CMD_NEED_NETDEV |
5492 WIPHY_VENDOR_CMD_NEED_RUNNING,
5493 .doit = wlan_hdd_cfg80211_keymgmt_set_key
5494 },
5495#endif
5496#ifdef FEATURE_WLAN_EXTSCAN
5497 {
5498 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5499 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
5500 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5501 WIPHY_VENDOR_CMD_NEED_NETDEV |
5502 WIPHY_VENDOR_CMD_NEED_RUNNING,
5503 .doit = wlan_hdd_cfg80211_set_passpoint_list
5504 },
5505 {
5506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5507 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
5508 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5509 WIPHY_VENDOR_CMD_NEED_NETDEV |
5510 WIPHY_VENDOR_CMD_NEED_RUNNING,
5511 .doit = wlan_hdd_cfg80211_reset_passpoint_list
5512 },
5513 {
5514 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5515 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
5516 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5517 WIPHY_VENDOR_CMD_NEED_NETDEV |
5518 WIPHY_VENDOR_CMD_NEED_RUNNING,
5519 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
5520 },
5521 {
5522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
5524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5525 WIPHY_VENDOR_CMD_NEED_NETDEV |
5526 WIPHY_VENDOR_CMD_NEED_RUNNING,
5527 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
5528 },
5529#endif /* FEATURE_WLAN_EXTSCAN */
5530 {
5531 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5532 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
5533 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5534 WIPHY_VENDOR_CMD_NEED_NETDEV,
5535 .doit = wlan_hdd_cfg80211_get_wifi_info
5536 },
5537 {
5538 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5539 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
5540 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5541 WIPHY_VENDOR_CMD_NEED_NETDEV |
5542 WIPHY_VENDOR_CMD_NEED_RUNNING,
5543 .doit = wlan_hdd_cfg80211_wifi_configuration_set
5544 },
5545 {
5546 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5547 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
5548 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5549 WIPHY_VENDOR_CMD_NEED_NETDEV,
5550 .doit = wlan_hdd_cfg80211_set_ext_roam_params
5551 },
5552 {
5553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
5555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5556 WIPHY_VENDOR_CMD_NEED_NETDEV,
5557 .doit = wlan_hdd_cfg80211_wifi_logger_start
5558 },
5559 {
5560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
5562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5563 WIPHY_VENDOR_CMD_NEED_NETDEV,
5564 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
5565 },
5566 {
5567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5568 .info.subcmd =
5569 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
5570 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5571 WIPHY_VENDOR_CMD_NEED_NETDEV |
5572 WIPHY_VENDOR_CMD_NEED_RUNNING,
5573 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
5574 },
5575 {
5576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5577 .info.subcmd =
5578 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
5579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5580 WIPHY_VENDOR_CMD_NEED_NETDEV |
5581 WIPHY_VENDOR_CMD_NEED_RUNNING,
5582 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
5583 },
5584#ifdef FEATURE_WLAN_TDLS
5585 {
5586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
5588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5589 WIPHY_VENDOR_CMD_NEED_NETDEV |
5590 WIPHY_VENDOR_CMD_NEED_RUNNING,
5591 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
5592 },
5593#endif
5594#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5595 {
5596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
5598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5599 WIPHY_VENDOR_CMD_NEED_NETDEV |
5600 WIPHY_VENDOR_CMD_NEED_RUNNING,
5601 .doit = wlan_hdd_cfg80211_offloaded_packets
5602 },
5603#endif
5604 {
5605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
5607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5608 WIPHY_VENDOR_CMD_NEED_NETDEV |
5609 WIPHY_VENDOR_CMD_NEED_RUNNING,
5610 .doit = wlan_hdd_cfg80211_monitor_rssi
5611 },
5612 {
5613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
5615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5616 WIPHY_VENDOR_CMD_NEED_NETDEV |
5617 WIPHY_VENDOR_CMD_NEED_RUNNING,
5618 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
5619 },
5620#ifdef WLAN_FEATURE_MEMDUMP
5621 {
5622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
5624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5625 WIPHY_VENDOR_CMD_NEED_NETDEV |
5626 WIPHY_VENDOR_CMD_NEED_RUNNING,
5627 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
5628 },
5629#endif /* WLAN_FEATURE_MEMDUMP */
5630 {
5631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
5633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5634 WIPHY_VENDOR_CMD_NEED_NETDEV |
5635 WIPHY_VENDOR_CMD_NEED_RUNNING,
5636 .doit = wlan_hdd_cfg80211_vendor_scan
5637 },
5638
5639 /* OCB commands */
5640 {
5641 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5642 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
5643 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5644 WIPHY_VENDOR_CMD_NEED_NETDEV |
5645 WIPHY_VENDOR_CMD_NEED_RUNNING,
5646 .doit = wlan_hdd_cfg80211_ocb_set_config
5647 },
5648 {
5649 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5650 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
5651 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5652 WIPHY_VENDOR_CMD_NEED_NETDEV |
5653 WIPHY_VENDOR_CMD_NEED_RUNNING,
5654 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
5655 },
5656 {
5657 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5658 .info.subcmd =
5659 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
5660 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5661 WIPHY_VENDOR_CMD_NEED_NETDEV |
5662 WIPHY_VENDOR_CMD_NEED_RUNNING,
5663 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
5664 },
5665 {
5666 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5667 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
5668 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5669 WIPHY_VENDOR_CMD_NEED_NETDEV |
5670 WIPHY_VENDOR_CMD_NEED_RUNNING,
5671 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
5672 },
5673 {
5674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5675 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
5676 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5677 WIPHY_VENDOR_CMD_NEED_NETDEV |
5678 WIPHY_VENDOR_CMD_NEED_RUNNING,
5679 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
5680 },
5681 {
5682 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5683 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
5684 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5685 WIPHY_VENDOR_CMD_NEED_NETDEV |
5686 WIPHY_VENDOR_CMD_NEED_RUNNING,
5687 .doit = wlan_hdd_cfg80211_dcc_get_stats
5688 },
5689 {
5690 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5691 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
5692 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5693 WIPHY_VENDOR_CMD_NEED_NETDEV |
5694 WIPHY_VENDOR_CMD_NEED_RUNNING,
5695 .doit = wlan_hdd_cfg80211_dcc_clear_stats
5696 },
5697 {
5698 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5699 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
5700 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5701 WIPHY_VENDOR_CMD_NEED_NETDEV |
5702 WIPHY_VENDOR_CMD_NEED_RUNNING,
5703 .doit = wlan_hdd_cfg80211_dcc_update_ndl
5704 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305705 {
5706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5707 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
5708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5709 WIPHY_VENDOR_CMD_NEED_NETDEV |
5710 WIPHY_VENDOR_CMD_NEED_RUNNING,
5711 .doit = wlan_hdd_cfg80211_get_link_properties
5712 },
Peng Xu278d0122015-09-24 16:34:17 -07005713 {
5714 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
5715 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5716 WIPHY_VENDOR_CMD_NEED_NETDEV |
5717 WIPHY_VENDOR_CMD_NEED_RUNNING,
5718 .doit = wlan_hdd_cfg80211_set_ota_test
5719 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08005720#ifdef FEATURE_LFR_SUBNET_DETECTION
5721 {
5722 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5723 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
5724 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5725 WIPHY_VENDOR_CMD_NEED_NETDEV |
5726 WIPHY_VENDOR_CMD_NEED_RUNNING,
5727 .doit = wlan_hdd_cfg80211_set_gateway_params
5728 },
5729#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07005730 {
5731 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
5732 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5733 WIPHY_VENDOR_CMD_NEED_NETDEV |
5734 WIPHY_VENDOR_CMD_NEED_RUNNING,
5735 .doit = wlan_hdd_cfg80211_txpower_scale
5736 },
5737 {
5738 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5739 .info.subcmd =
5740 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
5741 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5742 WIPHY_VENDOR_CMD_NEED_NETDEV |
5743 WIPHY_VENDOR_CMD_NEED_RUNNING,
5744 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
5745 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305746 {
5747 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5748 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
5749 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5750 WIPHY_VENDOR_CMD_NEED_NETDEV |
5751 WIPHY_VENDOR_CMD_NEED_RUNNING,
5752 .doit = wlan_hdd_cfg80211_bpf_offload
5753 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754};
5755
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005756/**
5757 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
5758 * @priv_size: Size of the hdd context.
5759 *
5760 * Allocate wiphy context and hdd context.
5761 *
5762 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005764hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005765{
5766 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005767 hdd_context_t *hdd_ctx;
5768
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005769 ENTER();
5770
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
5772
5773 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005774 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005775 return NULL;
5776 }
5777
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005778 hdd_ctx = wiphy_priv(wiphy);
5779
5780 hdd_ctx->wiphy = wiphy;
5781
5782 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783}
5784
5785/*
5786 * FUNCTION: wlan_hdd_cfg80211_update_band
5787 * This function is called from the supplicant through a
5788 * private ioctl to change the band value
5789 */
5790int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
5791{
5792 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07005793 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005794
5795 ENTER();
5796
5797 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5798
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005799 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005800 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801
5802 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5803 struct ieee80211_supported_band *band = wiphy->bands[i];
5804
5805 channelEnabledState =
5806 cds_get_channel_state(band->channels[j].
5807 hw_value);
5808
5809 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
5810 /* 5G only */
5811#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5812 /* Enable Social channels for P2P */
5813 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5814 (band->channels[j].center_freq)
5815 && CHANNEL_STATE_ENABLE ==
5816 channelEnabledState)
5817 band->channels[j].flags &=
5818 ~IEEE80211_CHAN_DISABLED;
5819 else
5820#endif
5821 band->channels[j].flags |=
5822 IEEE80211_CHAN_DISABLED;
5823 continue;
5824 } else if (IEEE80211_BAND_5GHZ == i &&
5825 eCSR_BAND_24 == eBand) {
5826 /* 2G only */
5827 band->channels[j].flags |=
5828 IEEE80211_CHAN_DISABLED;
5829 continue;
5830 }
5831
Amar Singhal6842e8f2016-02-23 16:30:32 -08005832 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 band->channels[j].flags &=
5834 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 }
5836 }
5837 return 0;
5838}
5839
5840/*
5841 * FUNCTION: wlan_hdd_cfg80211_init
5842 * This function is called by hdd_wlan_startup()
5843 * during initialization.
5844 * This function is used to initialize and register wiphy structure.
5845 */
5846int wlan_hdd_cfg80211_init(struct device *dev,
5847 struct wiphy *wiphy, struct hdd_config *pCfg)
5848{
5849 int i, j;
5850 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5851
5852 ENTER();
5853
5854 /* Now bind the underlying wlan device with wiphy */
5855 set_wiphy_dev(wiphy, dev);
5856
5857 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
5858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005859#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
5860 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005861 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862#else
5863 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005864 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865#endif
5866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
5868 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
5869 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
5870#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
5871 | WIPHY_FLAG_4ADDR_STATION
5872#endif
5873 | WIPHY_FLAG_OFFCHAN_TX;
5874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005875#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5876 wiphy->wowlan = &wowlan_support_cfg80211_init;
5877#else
5878 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
5879 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
5880 wiphy->wowlan.pattern_min_len = 1;
5881 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
5882#endif
5883
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07005884 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885#ifdef FEATURE_WLAN_ESE
5886 || pCfg->isEseIniFeatureEnabled
5887#endif
5888 ) {
5889 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
5890 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005891#ifdef FEATURE_WLAN_TDLS
5892 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
5893 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
5894#endif
5895
5896 wiphy->features |= NL80211_FEATURE_HT_IBSS;
5897
5898#ifdef FEATURE_WLAN_SCAN_PNO
5899 if (pCfg->configPNOScanSupport) {
5900 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5901 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
5902 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
5903 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
5904 }
5905#endif /*FEATURE_WLAN_SCAN_PNO */
5906
5907#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05305908 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005909#endif
5910
5911 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
5912 driver can still register regulatory callback and
5913 it will get regulatory settings in wiphy->band[], but
5914 driver need to determine what to do with both
5915 regulatory settings */
5916
5917 wiphy->reg_notifier = hdd_reg_notifier;
5918
5919#if defined QCA_WIFI_FTM
5920}
5921#endif
5922
5923 wiphy->max_scan_ssids = MAX_SCAN_SSID;
5924
5925 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
5926
5927 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
5928
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07005929 if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE) {
5930 /* Supports STATION & AD-HOC modes right now */
5931 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
5932 | BIT(NL80211_IFTYPE_ADHOC)
5933 | BIT(NL80211_IFTYPE_P2P_CLIENT)
5934 | BIT(NL80211_IFTYPE_P2P_GO)
5935 | BIT(NL80211_IFTYPE_AP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07005937 if (pCfg->advertiseConcurrentOperation) {
5938 if (pCfg->enableMCC) {
5939 int i;
5940
5941 for (i = 0;
5942 i < ARRAY_SIZE(wlan_hdd_iface_combination);
5943 i++) {
5944 if (!pCfg->allowMCCGODiffBI)
5945 wlan_hdd_iface_combination[i].
5946 beacon_int_infra_match = true;
5947 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005948 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07005949 wiphy->n_iface_combinations =
5950 ARRAY_SIZE(wlan_hdd_iface_combination);
5951 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07005953 } else {
5954 wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005955 wiphy->n_iface_combinations =
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07005956 ARRAY_SIZE(wlan_hdd_mon_iface);
5957 wiphy->iface_combinations = wlan_hdd_mon_iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005958 }
5959
5960 /* Before registering we need to update the ht capabilitied based
5961 * on ini values*/
5962 if (!pCfg->ShortGI20MhzEnable) {
5963 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5964 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5965 wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &=
5966 ~IEEE80211_HT_CAP_SGI_20;
5967 }
5968
5969 if (!pCfg->ShortGI40MhzEnable) {
5970 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
5971 }
5972
5973 if (!pCfg->nChannelBondingMode5GHz) {
5974 wlan_hdd_band_5_ghz.ht_cap.cap &=
5975 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5976 }
5977
5978 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
5979 if (true == hdd_is_5g_supported(pHddCtx)) {
5980 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
5981 }
5982
5983 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5984
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005985 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005987
5988 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5989 struct ieee80211_supported_band *band = wiphy->bands[i];
5990
5991 if (IEEE80211_BAND_2GHZ == i &&
5992 eCSR_BAND_5G == pCfg->nBandCapability) {
5993 /* 5G only */
5994#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5995 /* Enable social channels for P2P */
5996 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5997 (band->channels[j].center_freq))
5998 band->channels[j].flags &=
5999 ~IEEE80211_CHAN_DISABLED;
6000 else
6001#endif
6002 band->channels[j].flags |=
6003 IEEE80211_CHAN_DISABLED;
6004 continue;
6005 } else if (IEEE80211_BAND_5GHZ == i &&
6006 eCSR_BAND_24 == pCfg->nBandCapability) {
6007 /* 2G only */
6008 band->channels[j].flags |=
6009 IEEE80211_CHAN_DISABLED;
6010 continue;
6011 }
6012 }
6013 }
6014 /*Initialise the supported cipher suite details */
6015 wiphy->cipher_suites = hdd_cipher_suites;
6016 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
6017
6018 /*signal strength in mBm (100*dBm) */
6019 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
6020 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
6021
Anurag Chouhan6d760662016-02-20 16:05:43 +05306022 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023 wiphy->n_vendor_commands =
6024 ARRAY_SIZE(hdd_wiphy_vendor_commands);
6025 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
6026
6027 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
6028 wiphy->n_vendor_events =
6029 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
6030 }
6031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006032 if (pCfg->enableDFSMasterCap) {
6033 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
6034 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006035
6036 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
6037
6038#ifdef QCA_HT_2040_COEX
6039 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
6040#endif
6041
Abhishek Singh1bdb1572015-10-16 16:24:19 +05306042 hdd_add_channel_switch_support(&wiphy->flags);
6043
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044 EXIT();
6045 return 0;
6046}
6047
6048/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306049 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006050 * initialization. In wlan_hdd_cfg80211_init, only the
6051 * default values will be initialized. The final initialization
6052 * of all required members can be done here.
6053 */
6054void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
6055{
6056 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
6057}
6058
6059/* In this function we are registering wiphy. */
6060int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
6061{
6062 ENTER();
6063 /* Register our wiphy dev with cfg80211 */
6064 if (0 > wiphy_register(wiphy)) {
6065 /* print error */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306066 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: wiphy register failed",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006067 __func__);
6068 return -EIO;
6069 }
6070
6071 EXIT();
6072 return 0;
6073}
6074
6075/*
6076 HDD function to update wiphy capability based on target offload status.
6077
6078 wlan_hdd_cfg80211_init() does initialization of all wiphy related
6079 capability even before downloading firmware to the target. In discrete
6080 case, host will get know certain offload capability (say sched_scan
6081 caps) only after downloading firmware to the target and target boots up.
6082 This function is used to override setting done in wlan_hdd_cfg80211_init()
6083 based on target capability.
6084 */
6085void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
6086{
6087#ifdef FEATURE_WLAN_SCAN_PNO
6088 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6089 struct hdd_config *pCfg = pHddCtx->config;
6090
6091 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
6092 * control comes here. Here just we need to clear it if firmware doesn't
6093 * have PNO support. */
6094 if (!pCfg->PnoOffload) {
6095 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6096 wiphy->max_sched_scan_ssids = 0;
6097 wiphy->max_match_sets = 0;
6098 wiphy->max_sched_scan_ie_len = 0;
6099 }
6100#endif
6101}
6102
6103/* This function registers for all frame which supplicant is interested in */
6104void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
6105{
6106 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6107 /* Register for all P2P action, public action etc frames */
6108 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
6109
6110 ENTER();
6111
Abhishek Singh7996eb72015-12-30 17:24:02 +05306112 /* Register frame indication call back */
6113 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
6114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006115 /* Right now we are registering these frame when driver is getting
6116 initialized. Once we will move to 2.6.37 kernel, in which we have
6117 frame register ops, we will move this code as a part of that */
6118 /* GAS Initial Request */
6119 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6120 (uint8_t *) GAS_INITIAL_REQ,
6121 GAS_INITIAL_REQ_SIZE);
6122
6123 /* GAS Initial Response */
6124 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6125 (uint8_t *) GAS_INITIAL_RSP,
6126 GAS_INITIAL_RSP_SIZE);
6127
6128 /* GAS Comeback Request */
6129 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6130 (uint8_t *) GAS_COMEBACK_REQ,
6131 GAS_COMEBACK_REQ_SIZE);
6132
6133 /* GAS Comeback Response */
6134 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6135 (uint8_t *) GAS_COMEBACK_RSP,
6136 GAS_COMEBACK_RSP_SIZE);
6137
6138 /* P2P Public Action */
6139 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6140 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
6141 P2P_PUBLIC_ACTION_FRAME_SIZE);
6142
6143 /* P2P Action */
6144 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6145 (uint8_t *) P2P_ACTION_FRAME,
6146 P2P_ACTION_FRAME_SIZE);
6147
6148 /* WNM BSS Transition Request frame */
6149 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6150 (uint8_t *) WNM_BSS_ACTION_FRAME,
6151 WNM_BSS_ACTION_FRAME_SIZE);
6152
6153 /* WNM-Notification */
6154 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
6155 (uint8_t *) WNM_NOTIFICATION_FRAME,
6156 WNM_NOTIFICATION_FRAME_SIZE);
6157}
6158
6159void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
6160{
6161 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6162 /* Register for all P2P action, public action etc frames */
6163 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
6164
6165 ENTER();
6166
6167 /* Right now we are registering these frame when driver is getting
6168 initialized. Once we will move to 2.6.37 kernel, in which we have
6169 frame register ops, we will move this code as a part of that */
6170 /* GAS Initial Request */
6171
6172 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6173 (uint8_t *) GAS_INITIAL_REQ,
6174 GAS_INITIAL_REQ_SIZE);
6175
6176 /* GAS Initial Response */
6177 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6178 (uint8_t *) GAS_INITIAL_RSP,
6179 GAS_INITIAL_RSP_SIZE);
6180
6181 /* GAS Comeback Request */
6182 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6183 (uint8_t *) GAS_COMEBACK_REQ,
6184 GAS_COMEBACK_REQ_SIZE);
6185
6186 /* GAS Comeback Response */
6187 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6188 (uint8_t *) GAS_COMEBACK_RSP,
6189 GAS_COMEBACK_RSP_SIZE);
6190
6191 /* P2P Public Action */
6192 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6193 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
6194 P2P_PUBLIC_ACTION_FRAME_SIZE);
6195
6196 /* P2P Action */
6197 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6198 (uint8_t *) P2P_ACTION_FRAME,
6199 P2P_ACTION_FRAME_SIZE);
6200
6201 /* WNM-Notification */
6202 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
6203 (uint8_t *) WNM_NOTIFICATION_FRAME,
6204 WNM_NOTIFICATION_FRAME_SIZE);
6205}
6206
6207#ifdef FEATURE_WLAN_WAPI
6208void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
6209 const uint8_t *mac_addr, const uint8_t *key,
6210 int key_Len)
6211{
6212 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6213 tCsrRoamSetKey setKey;
6214 bool isConnected = true;
6215 int status = 0;
6216 uint32_t roamId = 0xFF;
6217 uint8_t *pKeyPtr = NULL;
6218 int n = 0;
6219
6220 hddLog(LOG1, "Device_mode %s(%d)",
6221 hdd_device_mode_to_string(pAdapter->device_mode),
6222 pAdapter->device_mode);
6223
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306224 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006225 setKey.keyId = key_index; /* Store Key ID */
6226 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
6227 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
6228 setKey.paeRole = 0; /* the PAE role */
6229 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05306230 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006231 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306232 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006233 }
6234 setKey.keyLength = key_Len;
6235 pKeyPtr = setKey.Key;
6236 memcpy(pKeyPtr, key, key_Len);
6237
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306238 hddLog(QDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006239 __func__, key_Len);
6240 for (n = 0; n < key_Len; n++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306241 hddLog(QDF_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006242 __func__, n, setKey.Key[n]);
6243
6244 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6245 if (isConnected) {
6246 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6247 pAdapter->sessionId, &setKey, &roamId);
6248 }
6249 if (status != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306250 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006251 "[%4d] sme_roam_set_key returned ERROR status= %d",
6252 __LINE__, status);
6253 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
6254 }
6255}
6256#endif /* FEATURE_WLAN_WAPI */
6257
6258uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
6259 uint8_t eid)
6260{
6261 int left = length;
6262 uint8_t *ptr = (uint8_t *)ies_ptr;
6263 uint8_t elem_id, elem_len;
6264
6265 while (left >= 2) {
6266 elem_id = ptr[0];
6267 elem_len = ptr[1];
6268 left -= 2;
6269 if (elem_len > left) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306270 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006271 FL("Invalid IEs eid = %d elem_len=%d left=%d"),
6272 eid, elem_len, left);
6273 return NULL;
6274 }
6275 if (elem_id == eid) {
6276 return ptr;
6277 }
6278
6279 left -= elem_len;
6280 ptr += (elem_len + 2);
6281 }
6282 return NULL;
6283}
6284
6285/*
6286 * FUNCTION: wlan_hdd_validate_operation_channel
6287 * called by wlan_hdd_cfg80211_start_bss() and
6288 * wlan_hdd_set_channel()
6289 * This function validates whether given channel is part of valid
6290 * channel list.
6291 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306292QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006293 int channel)
6294{
6295
6296 uint32_t num_ch = 0;
6297 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6298 u32 indx = 0;
6299 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6300 uint8_t fValidChannel = false, count = 0;
6301 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
6302
6303 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6304
6305 if (hdd_pConfig_ini->sapAllowAllChannel) {
6306 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08006307 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006308 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309 fValidChannel = true;
6310 break;
6311 }
6312 }
6313 if (fValidChannel != true) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306314 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006315 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306316 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006317 }
6318 } else {
6319 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6320 valid_ch, &num_ch)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306321 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006322 "%s: failed to get valid channel list",
6323 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306324 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006325 }
6326 for (indx = 0; indx < num_ch; indx++) {
6327 if (channel == valid_ch[indx]) {
6328 break;
6329 }
6330 }
6331
6332 if (indx >= num_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306333 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006334 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306335 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006336 }
6337 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306338 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006339
6340}
6341
6342#ifdef DHCP_SERVER_OFFLOAD
6343static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
6344{
6345 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
6346 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
6347 uint8_t numEntries = 0;
6348 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
6349 uint8_t num;
6350 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306351 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 if (NULL == pDhcpSrvInfo) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306353 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006354 "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
6355 return;
6356 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306357 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006358 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
6359 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
6360 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
6361 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
6362 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
6363 if (numEntries != IPADDR_NUM_ENTRIES) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306364 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006365 "%s: incorrect IP address (%s) assigned for DHCP server!",
6366 __func__, pHddCtx->config->dhcpServerIP);
6367 goto end;
6368 }
6369 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306370 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006371 "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
6372 __func__, pHddCtx->config->dhcpServerIP);
6373 goto end;
6374 }
6375 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306376 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006377 "%s: invalid IP address (%s)! The last field must be less than 100!",
6378 __func__, pHddCtx->config->dhcpServerIP);
6379 goto end;
6380 }
6381 for (num = 0; num < numEntries; num++) {
6382 temp = srv_ip[num];
6383 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
6384 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306385 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006386 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306387 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006388 "%s: sme_setDHCPSrvOffload fail!", __func__);
6389 goto end;
6390 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306391 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006392 "%s: enable DHCP Server offload successfully!", __func__);
6393end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306394 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006395 return;
6396}
6397#endif /* DHCP_SERVER_OFFLOAD */
6398
6399static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6400 struct net_device *dev,
6401 struct bss_parameters *params)
6402{
6403 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6404 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6405 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306406 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006407
6408 ENTER();
6409
Anurag Chouhan6d760662016-02-20 16:05:43 +05306410 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006411 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6412 return -EINVAL;
6413 }
6414
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306415 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006416 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
6417 pAdapter->sessionId, params->ap_isolate));
6418 hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"),
6419 hdd_device_mode_to_string(pAdapter->device_mode),
6420 pAdapter->device_mode, params->ap_isolate);
6421
6422 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6423 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306424 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006425 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006426
Krunal Sonib4326f22016-03-10 13:05:51 -08006427 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
6428 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006429 return -EOPNOTSUPP;
6430 }
6431
6432 /* ap_isolate == -1 means that in change bss, upper layer doesn't
6433 * want to update this parameter */
6434 if (-1 != params->ap_isolate) {
6435 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
6436 !!params->ap_isolate;
6437
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306438 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006439 pAdapter->sessionId,
6440 pAdapter->sessionCtx.
6441 ap.
6442 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306443 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006444 ret = -EINVAL;
6445 }
6446 }
6447
6448 EXIT();
6449 return ret;
6450}
6451
Krunal Soni8c37e322016-02-03 16:08:37 -08006452/**
6453 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
6454 * @ndev: pointer to net device provided by supplicant
6455 * @type: type of the interface, upper layer wanted to change
6456 *
6457 * Upper layer provides the new interface mode that needs to be changed
6458 * for given net device
6459 *
6460 * Return: success or failure in terms of integer value
6461 */
6462static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006463 enum nl80211_iftype type)
6464{
Krunal Soni8c37e322016-02-03 16:08:37 -08006465 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6466 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6467 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006468 hdd_wext_state_t *wext;
6469 struct wireless_dev *wdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306470 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006471
6472 ENTER();
6473
Krunal Soni8c37e322016-02-03 16:08:37 -08006474 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006475 hddLog(LOG1, FL("ACS is in progress, don't change iface!"));
6476 return 0;
6477 }
6478
6479 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08006480 hdd_stop_adapter(hdd_ctx, adapter, true);
6481 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482 wdev->iftype = type;
6483 /*Check for sub-string p2p to confirm its a p2p interface */
6484 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08006485 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006486 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006487 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08006488 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08006489 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006490 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08006491 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006492 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006493 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006494 }
Krunal Soni8c37e322016-02-03 16:08:37 -08006495 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
6496 hdd_set_station_ops(adapter->dev);
6497 status = hdd_init_station_mode(adapter);
6498 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
6499 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006500 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08006501 adapter->scan_info.scanAddIE.length;
6502 if (type == NL80211_IFTYPE_ADHOC) {
6503 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
6504 wext->roamProfile.phyMode =
6505 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
6506 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006507 EXIT();
6508 return status;
6509}
6510
6511static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6512 struct net_device *dev,
6513 struct bss_parameters *params)
6514{
6515 int ret;
6516
6517 cds_ssr_protect(__func__);
6518 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
6519 cds_ssr_unprotect(__func__);
6520
6521 return ret;
6522}
6523
6524/* FUNCTION: wlan_hdd_change_country_code_cd
6525 * to wait for contry code completion
6526 */
6527void *wlan_hdd_change_country_code_cb(void *pAdapter)
6528{
6529 hdd_adapter_t *call_back_pAdapter = pAdapter;
6530 complete(&call_back_pAdapter->change_country_code);
6531 return NULL;
6532}
6533
Rajeev Kumar98edb772016-01-19 12:42:19 -08006534/**
6535 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6536 * @wiphy: Pointer to the wiphy structure
6537 * @ndev: Pointer to the net device
6538 * @type: Interface type
6539 * @flags: Flags for change interface
6540 * @params: Pointer to change interface parameters
6541 *
6542 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006543 */
6544static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6545 struct net_device *ndev,
6546 enum nl80211_iftype type,
6547 u32 *flags,
6548 struct vif_params *params)
6549{
6550 struct wireless_dev *wdev;
6551 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6552 hdd_context_t *pHddCtx;
6553 tCsrRoamProfile *pRoamProfile = NULL;
6554 eCsrRoamBssType LastBSSType;
6555 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306556 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006557 int status;
6558
6559 ENTER();
6560
Anurag Chouhan6d760662016-02-20 16:05:43 +05306561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006562 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6563 return -EINVAL;
6564 }
6565
6566 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6567 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306568 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006569 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006570
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306571 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006572 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
6573 pAdapter->sessionId, type));
6574
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306575 hddLog(QDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006576 pAdapter->device_mode, type);
6577
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006578 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006579 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
6580 0, HW_MODE_20_MHZ)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306581 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006582 FL("This concurrency combination is not allowed"));
6583 return -EINVAL;
6584 }
6585
6586 pConfig = pHddCtx->config;
6587 wdev = ndev->ieee80211_ptr;
6588
6589 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006590 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006591
6592 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
6593
Krunal Sonib4326f22016-03-10 13:05:51 -08006594 if ((pAdapter->device_mode == QDF_STA_MODE) ||
6595 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
6596 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
6597 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006598 hdd_wext_state_t *pWextState =
6599 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6600
6601 pRoamProfile = &pWextState->roamProfile;
6602 LastBSSType = pRoamProfile->BSSType;
6603
6604 switch (type) {
6605 case NL80211_IFTYPE_STATION:
6606 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08006607 case NL80211_IFTYPE_ADHOC:
6608 if (type == NL80211_IFTYPE_ADHOC) {
6609 wlan_hdd_tdls_exit(pAdapter);
6610 hdd_deregister_tx_flow_control(pAdapter);
6611 hddLog(LOG1,
6612 FL("Setting interface Type to ADHOC"));
6613 }
6614 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
6615 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306616 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006617 return -EINVAL;
6618
Krunal Soni8c37e322016-02-03 16:08:37 -08006619 /*
6620 * for ibss interface type flow control is not required
6621 * so don't register tx flow control
6622 */
6623 if (type != NL80211_IFTYPE_ADHOC)
6624 hdd_register_tx_flow_control(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006625 hdd_tx_resume_timer_expired_handler,
6626 hdd_tx_resume_cb);
6627
6628 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006629 case NL80211_IFTYPE_AP:
6630 case NL80211_IFTYPE_P2P_GO:
6631 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306632 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006633 FL("Setting interface Type to %s"),
6634 (type ==
6635 NL80211_IFTYPE_AP) ? "SoftAP" :
6636 "P2pGo");
6637
6638 /* Cancel any remain on channel for GO mode */
6639 if (NL80211_IFTYPE_P2P_GO == type) {
6640 wlan_hdd_cancel_existing_remain_on_channel
6641 (pAdapter);
6642 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006643 hdd_stop_adapter(pHddCtx, pAdapter, true);
6644
6645 /* De-init the adapter */
6646 hdd_deinit_adapter(pHddCtx, pAdapter, true);
6647 memset(&pAdapter->sessionCtx, 0,
6648 sizeof(pAdapter->sessionCtx));
6649 pAdapter->device_mode =
6650 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08006651 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
6652 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006653
6654 /*
6655 * Fw will take care incase of concurrency
6656 */
6657
Krunal Sonib4326f22016-03-10 13:05:51 -08006658 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006659 && (pConfig->apRandomBssidEnabled)) {
6660 /* To meet Android requirements create a randomized
6661 MAC address of the form 02:1A:11:Fx:xx:xx */
6662 get_random_bytes(&ndev->dev_addr[3], 3);
6663 ndev->dev_addr[0] = 0x02;
6664 ndev->dev_addr[1] = 0x1A;
6665 ndev->dev_addr[2] = 0x11;
6666 ndev->dev_addr[3] |= 0xF0;
6667 memcpy(pAdapter->macAddressCurrent.
6668 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306669 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006670 pr_info("wlan: Generated HotSpot BSSID "
6671 MAC_ADDRESS_STR "\n",
6672 MAC_ADDR_ARRAY(ndev->dev_addr));
6673 }
6674
6675 hdd_set_ap_ops(pAdapter->dev);
6676
6677 vstatus = hdd_init_ap_mode(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306678 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006679 hddLog(LOGP,
6680 FL
6681 ("Error initializing the ap mode"));
6682 return -EINVAL;
6683 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006684
6685 hdd_register_tx_flow_control(pAdapter,
6686 hdd_softap_tx_resume_timer_expired_handler,
6687 hdd_softap_tx_resume_cb);
6688
6689 /* Interface type changed update in wiphy structure */
6690 if (wdev) {
6691 wdev->iftype = type;
6692 } else {
6693 hddLog(LOGE,
6694 FL("Wireless dev is NULL"));
6695 return -EINVAL;
6696 }
6697 goto done;
6698 }
6699
6700 default:
6701 hddLog(LOGE, FL("Unsupported interface type (%d)"),
6702 type);
6703 return -EOPNOTSUPP;
6704 }
Krunal Sonib4326f22016-03-10 13:05:51 -08006705 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
6706 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006707 switch (type) {
6708 case NL80211_IFTYPE_STATION:
6709 case NL80211_IFTYPE_P2P_CLIENT:
6710 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08006711 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
6712 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306713 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006714 return status;
6715
6716 if ((NL80211_IFTYPE_P2P_CLIENT == type) ||
6717 (NL80211_IFTYPE_STATION == type)) {
6718
6719 hdd_register_tx_flow_control(pAdapter,
6720 hdd_tx_resume_timer_expired_handler,
6721 hdd_tx_resume_cb);
6722 }
6723 goto done;
6724
6725 case NL80211_IFTYPE_AP:
6726 case NL80211_IFTYPE_P2P_GO:
6727 wdev->iftype = type;
6728 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006729 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006730
6731 hdd_register_tx_flow_control(pAdapter,
6732 hdd_softap_tx_resume_timer_expired_handler,
6733 hdd_softap_tx_resume_cb);
6734 goto done;
6735
6736 default:
6737 hddLog(LOGE, FL("Unsupported interface type(%d)"),
6738 type);
6739 return -EOPNOTSUPP;
6740 }
6741 } else {
6742 hddLog(LOGE, FL("Unsupported device mode(%d)"),
6743 pAdapter->device_mode);
6744 return -EOPNOTSUPP;
6745 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006746done:
6747 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006748 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006749
6750#ifdef WLAN_FEATURE_LPSS
6751 wlan_hdd_send_all_scan_intf_info(pHddCtx);
6752#endif
6753
6754 EXIT();
6755 return 0;
6756}
6757
Rajeev Kumar98edb772016-01-19 12:42:19 -08006758/**
6759 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6760 * @wiphy: Pointer to the wiphy structure
6761 * @ndev: Pointer to the net device
6762 * @type: Interface type
6763 * @flags: Flags for change interface
6764 * @params: Pointer to change interface parameters
6765 *
6766 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006767 */
6768static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6769 struct net_device *ndev,
6770 enum nl80211_iftype type,
6771 u32 *flags,
6772 struct vif_params *params)
6773{
6774 int ret;
6775
6776 cds_ssr_protect(__func__);
6777 ret =
6778 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
6779 cds_ssr_unprotect(__func__);
6780
6781 return ret;
6782}
6783
6784#ifdef FEATURE_WLAN_TDLS
6785static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
6786 int index, uint8_t match)
6787{
6788 int i;
6789 for (i = 0; i < index; i++) {
6790 if (arr[i] == match)
6791 return true;
6792 }
6793 return false;
6794}
6795#endif
6796
6797/**
6798 * __wlan_hdd_change_station() - change station
6799 * @wiphy: Pointer to the wiphy structure
6800 * @dev: Pointer to the net device.
6801 * @mac: bssid
6802 * @params: Pointer to station parameters
6803 *
6804 * Return: 0 for success, error number on failure.
6805 */
6806#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6807static int __wlan_hdd_change_station(struct wiphy *wiphy,
6808 struct net_device *dev,
6809 const uint8_t *mac,
6810 struct station_parameters *params)
6811#else
6812static int __wlan_hdd_change_station(struct wiphy *wiphy,
6813 struct net_device *dev,
6814 uint8_t *mac,
6815 struct station_parameters *params)
6816#endif
6817{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306818 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006819 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6820 hdd_context_t *pHddCtx;
6821 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306822 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006823#ifdef FEATURE_WLAN_TDLS
6824 tCsrStaParams StaParams = { 0 };
6825 uint8_t isBufSta = 0;
6826 uint8_t isOffChannelSupported = 0;
6827#endif
6828 int ret;
6829
6830 ENTER();
6831
Anurag Chouhan6d760662016-02-20 16:05:43 +05306832 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006833 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6834 return -EINVAL;
6835 }
6836
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306837 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006838 TRACE_CODE_HDD_CHANGE_STATION,
6839 pAdapter->sessionId, params->listen_interval));
6840
6841 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6842 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306843 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006844 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006845
6846 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6847
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306848 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006849
Krunal Sonib4326f22016-03-10 13:05:51 -08006850 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
6851 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006852 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
6853 status =
6854 hdd_softap_change_sta_state(pAdapter,
6855 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08006856 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006857
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306858 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306859 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006860 FL
6861 ("Not able to change TL state to AUTHENTICATED"));
6862 return -EINVAL;
6863 }
6864 }
Krunal Sonib4326f22016-03-10 13:05:51 -08006865 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
6866 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006867#ifdef FEATURE_WLAN_TDLS
6868 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6869 StaParams.capability = params->capability;
6870 StaParams.uapsd_queues = params->uapsd_queues;
6871 StaParams.max_sp = params->max_sp;
6872
6873 /* Convert (first channel , number of channels) tuple to
6874 * the total list of channels. This goes with the assumption
6875 * that if the first channel is < 14, then the next channels
6876 * are an incremental of 1 else an incremental of 4 till the number
6877 * of channels.
6878 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306879 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006880 "%s: params->supported_channels_len: %d",
6881 __func__, params->supported_channels_len);
6882 if (0 != params->supported_channels_len) {
6883 int i = 0, j = 0, k = 0, no_of_channels = 0;
6884 int num_unique_channels;
6885 int next;
6886 for (i = 0;
6887 i < params->supported_channels_len
6888 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
6889 int wifi_chan_index;
6890 if (!wlan_hdd_is_duplicate_channel
6891 (StaParams.supported_channels, j,
6892 params->supported_channels[i])) {
6893 StaParams.
6894 supported_channels[j] =
6895 params->
6896 supported_channels[i];
6897 } else {
6898 continue;
6899 }
6900 wifi_chan_index =
6901 ((StaParams.supported_channels[j] <=
6902 HDD_CHANNEL_14) ? 1 : 4);
6903 no_of_channels =
6904 params->supported_channels[i + 1];
6905
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306906 QDF_TRACE(QDF_MODULE_ID_HDD,
6907 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006908 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d",
6909 __func__, i, j, k, j,
6910 StaParams.
6911 supported_channels[j],
6912 wifi_chan_index,
6913 no_of_channels);
6914 for (k = 1; k <= no_of_channels &&
6915 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
6916 k++) {
6917 next =
6918 StaParams.
6919 supported_channels[j] +
6920 wifi_chan_index;
6921 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
6922 StaParams.
6923 supported_channels[j
6924 +
6925 1]
6926 = next;
6927 } else {
6928 continue;
6929 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306930 QDF_TRACE(QDF_MODULE_ID_HDD,
6931 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006932 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d",
6933 __func__, i, j, k,
6934 j + 1,
6935 StaParams.
6936 supported_channels[j +
6937 1]);
6938 j += 1;
6939 }
6940 }
6941 num_unique_channels = j + 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306942 QDF_TRACE(QDF_MODULE_ID_HDD,
6943 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006944 "%s: Unique Channel List", __func__);
6945 for (i = 0; i < num_unique_channels; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306946 QDF_TRACE(QDF_MODULE_ID_HDD,
6947 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006948 "%s: StaParams.supported_channels[%d]: %d,",
6949 __func__, i,
6950 StaParams.
6951 supported_channels[i]);
6952 }
6953 if (MAX_CHANNEL < num_unique_channels)
6954 num_unique_channels = MAX_CHANNEL;
6955 StaParams.supported_channels_len =
6956 num_unique_channels;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306957 QDF_TRACE(QDF_MODULE_ID_HDD,
6958 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006959 "%s: After removing duplcates StaParams.supported_channels_len: %d",
6960 __func__,
6961 StaParams.supported_channels_len);
6962 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306963 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006964 params->supported_oper_classes,
6965 params->supported_oper_classes_len);
6966 StaParams.supported_oper_classes_len =
6967 params->supported_oper_classes_len;
6968
6969 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306970 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006971 params->ext_capab,
6972 sizeof(StaParams.extn_capability));
6973
6974 if (NULL != params->ht_capa) {
6975 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306976 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006977 sizeof(tSirHTCap));
6978 }
6979
6980 StaParams.supported_rates_len =
6981 params->supported_rates_len;
6982
6983 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
6984 * The supported_rates array , for all the structures propogating till Add Sta
6985 * to the firmware has to be modified , if the supplicant (ieee80211) is
6986 * modified to send more rates.
6987 */
6988
6989 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
6990 */
6991 if (StaParams.supported_rates_len >
6992 SIR_MAC_MAX_SUPP_RATES)
6993 StaParams.supported_rates_len =
6994 SIR_MAC_MAX_SUPP_RATES;
6995
6996 if (0 != StaParams.supported_rates_len) {
6997 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306998 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006999 params->supported_rates,
7000 StaParams.supported_rates_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307001 QDF_TRACE(QDF_MODULE_ID_HDD,
7002 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007003 "Supported Rates with Length %d",
7004 StaParams.supported_rates_len);
7005 for (i = 0; i < StaParams.supported_rates_len;
7006 i++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307007 QDF_TRACE(QDF_MODULE_ID_HDD,
7008 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007009 "[%d]: %0x", i,
7010 StaParams.supported_rates[i]);
7011 }
7012
7013 if (NULL != params->vht_capa) {
7014 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307015 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007016 params->vht_capa,
7017 sizeof(tSirVHTCap));
7018 }
7019
7020 if (0 != params->ext_capab_len) {
7021 /*Define A Macro : TODO Sunil */
7022 if ((1 << 4) & StaParams.extn_capability[3]) {
7023 isBufSta = 1;
7024 }
7025 /* TDLS Channel Switching Support */
7026 if ((1 << 6) & StaParams.extn_capability[3]) {
7027 isOffChannelSupported = 1;
7028 }
7029 }
7030
7031 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
7032 &StaParams,
7033 isBufSta,
7034 isOffChannelSupported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307035 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307036 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007037 FL
7038 ("wlan_hdd_tdls_set_peer_caps failed!"));
7039 return -EINVAL;
7040 }
7041
7042 status =
7043 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
7044 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307045 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307046 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007047 FL("wlan_hdd_tdls_add_station failed!"));
7048 return -EINVAL;
7049 }
7050 }
7051#endif
7052 }
7053 EXIT();
7054 return ret;
7055}
7056
7057/**
7058 * wlan_hdd_change_station() - cfg80211 change station handler function
7059 * @wiphy: Pointer to the wiphy structure
7060 * @dev: Pointer to the net device.
7061 * @mac: bssid
7062 * @params: Pointer to station parameters
7063 *
7064 * This is the cfg80211 change station handler function which invokes
7065 * the internal function @__wlan_hdd_change_station with
7066 * SSR protection.
7067 *
7068 * Return: 0 for success, error number on failure.
7069 */
7070#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
7071static int wlan_hdd_change_station(struct wiphy *wiphy,
7072 struct net_device *dev,
7073 const u8 *mac,
7074 struct station_parameters *params)
7075#else
7076static int wlan_hdd_change_station(struct wiphy *wiphy,
7077 struct net_device *dev,
7078 u8 *mac,
7079 struct station_parameters *params)
7080#endif
7081{
7082 int ret;
7083
7084 cds_ssr_protect(__func__);
7085 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
7086 cds_ssr_unprotect(__func__);
7087
7088 return ret;
7089}
7090
7091/*
7092 * FUNCTION: __wlan_hdd_cfg80211_add_key
7093 * This function is used to initialize the key information
7094 */
7095static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
7096 struct net_device *ndev,
7097 u8 key_index, bool pairwise,
7098 const u8 *mac_addr,
7099 struct key_params *params)
7100{
7101 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7102 tCsrRoamSetKey setKey;
7103 int status;
7104 uint32_t roamId = 0xFF;
7105#ifndef WLAN_FEATURE_MBSSID
7106 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context;
7107#endif
7108 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307109 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007110 hdd_context_t *pHddCtx;
7111 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7112
7113 ENTER();
7114
Anurag Chouhan6d760662016-02-20 16:05:43 +05307115 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007116 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7117 return -EINVAL;
7118 }
7119
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307120 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007121 TRACE_CODE_HDD_CFG80211_ADD_KEY,
7122 pAdapter->sessionId, params->key_len));
7123 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7124 status = wlan_hdd_validate_context(pHddCtx);
7125
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307126 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007127 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007128
7129 hddLog(LOG1, FL("Device_mode %s(%d)"),
7130 hdd_device_mode_to_string(pAdapter->device_mode),
7131 pAdapter->device_mode);
7132
7133 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307134 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007135 __func__, key_index);
7136
7137 return -EINVAL;
7138 }
7139
7140 if (CSR_MAX_KEY_LEN < params->key_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307141 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007142 __func__, params->key_len);
7143
7144 return -EINVAL;
7145 }
7146
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307147 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007148 "%s: called with key index = %d & key length %d",
7149 __func__, key_index, params->key_len);
7150
7151 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307152 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007153 setKey.keyId = key_index;
7154 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307155 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007156
7157 switch (params->cipher) {
7158 case WLAN_CIPHER_SUITE_WEP40:
7159 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
7160 break;
7161
7162 case WLAN_CIPHER_SUITE_WEP104:
7163 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
7164 break;
7165
7166 case WLAN_CIPHER_SUITE_TKIP:
7167 {
7168 u8 *pKey = &setKey.Key[0];
7169 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
7170
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307171 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007172
7173 /*Supplicant sends the 32bytes key in this order
7174
7175 |--------------|----------|----------|
7176 | Tk1 |TX-MIC | RX Mic |
7177 |||--------------|----------|----------|
7178 <---16bytes---><--8bytes--><--8bytes-->
7179
7180 */
7181 /*Sme expects the 32 bytes key to be in the below order
7182
7183 |--------------|----------|----------|
7184 | Tk1 |RX-MIC | TX Mic |
7185 |||--------------|----------|----------|
7186 <---16bytes---><--8bytes--><--8bytes-->
7187 */
7188 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307189 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007190
7191 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307192 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007193
7194 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307195 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007196
7197 break;
7198 }
7199
7200 case WLAN_CIPHER_SUITE_CCMP:
7201 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
7202 break;
7203
7204#ifdef FEATURE_WLAN_WAPI
7205 case WLAN_CIPHER_SUITE_SMS4:
7206 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307207 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007208 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
7209 mac_addr, params->key,
7210 params->key_len);
7211 return 0;
7212 }
7213#endif
7214
7215#ifdef FEATURE_WLAN_ESE
7216 case WLAN_CIPHER_SUITE_KRK:
7217 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
7218 break;
7219#ifdef WLAN_FEATURE_ROAM_OFFLOAD
7220 case WLAN_CIPHER_SUITE_BTK:
7221 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
7222 break;
7223#endif
7224#endif
7225
7226#ifdef WLAN_FEATURE_11W
7227 case WLAN_CIPHER_SUITE_AES_CMAC:
7228 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
7229 break;
7230#endif
7231
7232 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307233 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007234 __func__, params->cipher);
7235 return -EOPNOTSUPP;
7236 }
7237
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307238 hddLog(QDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007239 __func__, setKey.encType);
7240
7241 if (!pairwise) {
7242 /* set group key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307243 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007244 "%s- %d: setting Broadcast key", __func__, __LINE__);
7245 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05307246 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007247 } else {
7248 /* set pairwise key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307249 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007250 "%s- %d: setting pairwise key", __func__, __LINE__);
7251 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307252 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007253 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007254 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007255 /* if a key is already installed, block all subsequent ones */
7256 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307257 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007258 "%s: IBSS key installed already", __func__);
7259 return 0;
7260 }
7261
7262 setKey.keyDirection = eSIR_TX_RX;
7263 /*Set the group key */
7264 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7265 pAdapter->sessionId, &setKey, &roamId);
7266
7267 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307268 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007269 "%s: sme_roam_set_key failed, returned %d",
7270 __func__, status);
7271 return -EINVAL;
7272 }
7273 /*Save the keys here and call sme_roam_set_key for setting
7274 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307275 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007276 &setKey, sizeof(tCsrRoamSetKey));
7277
7278 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
7279 return status;
7280 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007281 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
7282 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007283 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7284 if (pHostapdState->bssState == BSS_START) {
7285#ifdef WLAN_FEATURE_MBSSID
7286 status =
7287 wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR
7288 (pAdapter), &setKey);
7289#else
7290 status = wlansap_set_key_sta(p_cds_context, &setKey);
7291#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307292 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307293 QDF_TRACE(QDF_MODULE_ID_HDD,
7294 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007295 "[%4d] wlansap_set_key_sta returned ERROR status= %d",
7296 __LINE__, status);
7297 }
7298 }
7299
7300 /* Save the key in ap ctx for use on START_BASS and restart */
7301 if (pairwise ||
7302 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
7303 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307304 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007305 sizeof(tCsrRoamSetKey));
7306 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307307 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007308 sizeof(tCsrRoamSetKey));
7309
Krunal Sonib4326f22016-03-10 13:05:51 -08007310 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
7311 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007312 hdd_wext_state_t *pWextState =
7313 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7314 hdd_station_ctx_t *pHddStaCtx =
7315 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7316
7317 if (!pairwise) {
7318 /* set group key */
7319 if (pHddStaCtx->roam_info.deferKeyComplete) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307320 QDF_TRACE(QDF_MODULE_ID_HDD,
7321 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007322 "%s- %d: Perform Set key Complete",
7323 __func__, __LINE__);
7324 hdd_perform_roam_set_key_complete(pAdapter);
7325 }
7326 }
7327
7328 pWextState->roamProfile.Keys.KeyLength[key_index] =
7329 (u8) params->key_len;
7330
7331 pWextState->roamProfile.Keys.defaultIndex = key_index;
7332
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307333 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007334 KeyMaterial[key_index][0], params->key,
7335 params->key_len);
7336
7337 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
7338
7339 hddLog(LOG2,
7340 FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"),
7341 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
7342 setKey.keyDirection);
7343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007344 /* The supplicant may attempt to set the PTK once pre-authentication
7345 is done. Save the key in the UMAC and include it in the ADD BSS
7346 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307347 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007348 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307349 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307350 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007351 "%s: Update PreAuth Key success", __func__);
7352 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307353 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307354 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007355 "%s: Update PreAuth Key failed", __func__);
7356 return -EINVAL;
7357 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007358
7359 /* issue set key request to SME */
7360 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7361 pAdapter->sessionId, &setKey, &roamId);
7362
7363 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307364 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007365 "%s: sme_roam_set_key failed, returned %d",
7366 __func__, status);
7367 pHddStaCtx->roam_info.roamingState =
7368 HDD_ROAM_STATE_NONE;
7369 return -EINVAL;
7370 }
7371
7372 /* in case of IBSS as there was no information available about WEP keys during
7373 * IBSS join, group key intialized with NULL key, so re-initialize group key
7374 * with correct value*/
7375 if ((eCSR_BSS_TYPE_START_IBSS ==
7376 pWextState->roamProfile.BSSType)
7377 &&
7378 !((IW_AUTH_KEY_MGMT_802_1X ==
7379 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
7380 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
7381 pHddStaCtx->conn_info.authType)
7382 )
7383 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
7384 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
7385 )
7386 ) {
7387 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05307388 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007389
7390 hddLog(LOG2,
7391 FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"),
7392 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
7393 setKey.keyDirection);
7394
7395 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7396 pAdapter->sessionId, &setKey,
7397 &roamId);
7398
7399 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307400 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007401 "%s: sme_roam_set_key failed for group key (IBSS), returned %d",
7402 __func__, status);
7403 pHddStaCtx->roam_info.roamingState =
7404 HDD_ROAM_STATE_NONE;
7405 return -EINVAL;
7406 }
7407 }
7408 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307409 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007410 return 0;
7411}
7412
7413static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
7414 struct net_device *ndev,
7415 u8 key_index, bool pairwise,
7416 const u8 *mac_addr,
7417 struct key_params *params)
7418{
7419 int ret;
7420 cds_ssr_protect(__func__);
7421 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
7422 mac_addr, params);
7423 cds_ssr_unprotect(__func__);
7424
7425 return ret;
7426}
7427
7428/*
7429 * FUNCTION: __wlan_hdd_cfg80211_get_key
7430 * This function is used to get the key information
7431 */
7432static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7433 struct net_device *ndev,
7434 u8 key_index, bool pairwise,
7435 const u8 *mac_addr, void *cookie,
7436 void (*callback)(void *cookie,
7437 struct key_params *)
7438 )
7439{
7440 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7441 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7442 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
7443 struct key_params params;
7444
7445 ENTER();
7446
Anurag Chouhan6d760662016-02-20 16:05:43 +05307447 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007448 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7449 return -EINVAL;
7450 }
7451
7452 hddLog(LOG1, FL("Device_mode %s(%d)"),
7453 hdd_device_mode_to_string(pAdapter->device_mode),
7454 pAdapter->device_mode);
7455
7456 memset(&params, 0, sizeof(params));
7457
7458 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307459 hddLog(QDF_TRACE_LEVEL_ERROR, FL("invalid key index %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007460 key_index);
7461 return -EINVAL;
7462 }
7463
7464 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
7465 case eCSR_ENCRYPT_TYPE_NONE:
7466 params.cipher = IW_AUTH_CIPHER_NONE;
7467 break;
7468
7469 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
7470 case eCSR_ENCRYPT_TYPE_WEP40:
7471 params.cipher = WLAN_CIPHER_SUITE_WEP40;
7472 break;
7473
7474 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
7475 case eCSR_ENCRYPT_TYPE_WEP104:
7476 params.cipher = WLAN_CIPHER_SUITE_WEP104;
7477 break;
7478
7479 case eCSR_ENCRYPT_TYPE_TKIP:
7480 params.cipher = WLAN_CIPHER_SUITE_TKIP;
7481 break;
7482
7483 case eCSR_ENCRYPT_TYPE_AES:
7484 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
7485 break;
7486
7487 default:
7488 params.cipher = IW_AUTH_CIPHER_NONE;
7489 break;
7490 }
7491
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307492 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007493 TRACE_CODE_HDD_CFG80211_GET_KEY,
7494 pAdapter->sessionId, params.cipher));
7495
7496 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
7497 params.seq_len = 0;
7498 params.seq = NULL;
7499 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
7500 callback(cookie, &params);
7501
7502 EXIT();
7503 return 0;
7504}
7505
7506static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7507 struct net_device *ndev,
7508 u8 key_index, bool pairwise,
7509 const u8 *mac_addr, void *cookie,
7510 void (*callback)(void *cookie,
7511 struct key_params *)
7512 )
7513{
7514 int ret;
7515
7516 cds_ssr_protect(__func__);
7517 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
7518 mac_addr, cookie, callback);
7519 cds_ssr_unprotect(__func__);
7520
7521 return ret;
7522}
7523
7524/**
7525 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
7526 * @wiphy: wiphy interface context
7527 * @ndev: pointer to net device
7528 * @key_index: Key index used in 802.11 frames
7529 * @unicast: true if it is unicast key
7530 * @multicast: true if it is multicast key
7531 *
7532 * This function is required for cfg80211_ops API.
7533 * It is used to delete the key information
7534 * Underlying hardware implementation does not have API to delete the
7535 * encryption key. It is automatically deleted when the peer is
7536 * removed. Hence this function currently does nothing.
7537 * Future implementation may interprete delete key operation to
7538 * replacing the key with a random junk value, effectively making it
7539 * useless.
7540 *
7541 * Return: status code, always 0.
7542 */
7543
7544static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7545 struct net_device *ndev,
7546 u8 key_index,
7547 bool pairwise, const u8 *mac_addr)
7548{
7549 EXIT();
7550 return 0;
7551}
7552
7553/**
7554 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
7555 * @wiphy: Pointer to wiphy structure.
7556 * @dev: Pointer to net_device structure.
7557 * @key_index: key index
7558 * @pairwise: pairwise
7559 * @mac_addr: mac address
7560 *
7561 * This is the cfg80211 delete key handler function which invokes
7562 * the internal function @__wlan_hdd_cfg80211_del_key with
7563 * SSR protection.
7564 *
7565 * Return: 0 for success, error number on failure.
7566 */
7567static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7568 struct net_device *dev,
7569 u8 key_index,
7570 bool pairwise, const u8 *mac_addr)
7571{
7572 int ret;
7573
7574 cds_ssr_protect(__func__);
7575 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
7576 pairwise, mac_addr);
7577 cds_ssr_unprotect(__func__);
7578
7579 return ret;
7580}
7581
7582/*
7583 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
7584 * This function is used to set the default tx key index
7585 */
7586static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7587 struct net_device *ndev,
7588 u8 key_index,
7589 bool unicast, bool multicast)
7590{
7591 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7592 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7593 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7594 hdd_context_t *pHddCtx;
7595 int status;
7596
7597 ENTER();
7598
Anurag Chouhan6d760662016-02-20 16:05:43 +05307599 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007600 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7601 return -EINVAL;
7602 }
7603
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307604 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007605 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
7606 pAdapter->sessionId, key_index));
7607
7608 hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"),
7609 hdd_device_mode_to_string(pAdapter->device_mode),
7610 pAdapter->device_mode, key_index);
7611
7612 if (CSR_MAX_NUM_KEY <= key_index) {
7613 hddLog(LOGE, FL("Invalid key index %d"), key_index);
7614 return -EINVAL;
7615 }
7616
7617 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7618 status = wlan_hdd_validate_context(pHddCtx);
7619
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307620 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007621 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007622
Krunal Sonib4326f22016-03-10 13:05:51 -08007623 if ((pAdapter->device_mode == QDF_STA_MODE) ||
7624 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007625 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7626 pHddStaCtx->conn_info.ucEncryptionType) &&
7627 (eCSR_ENCRYPT_TYPE_AES !=
7628 pHddStaCtx->conn_info.ucEncryptionType)) {
7629 /* If default key index is not same as previous one,
7630 * then update the default key index */
7631
7632 tCsrRoamSetKey setKey;
7633 uint32_t roamId = 0xFF;
7634 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
7635
7636 hddLog(LOG2, FL("Default tx key index %d"), key_index);
7637
7638 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307639 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007640 setKey.keyId = key_index;
7641 setKey.keyLength = Keys->KeyLength[key_index];
7642
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307643 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007644 &Keys->KeyMaterial[key_index][0],
7645 Keys->KeyLength[key_index]);
7646
7647 setKey.keyDirection = eSIR_TX_RX;
7648
Anurag Chouhanc5548422016-02-24 18:33:27 +05307649 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007650 &pHddStaCtx->conn_info.bssId);
7651
7652 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
7653 pWextState->roamProfile.EncryptionType.
7654 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
7655 /* In the case of dynamic wep supplicant hardcodes DWEP type
7656 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
7657 * WEP-40 encryption. In this canse the key length is 5 but the
7658 * encryption type is 104 hence checking the key langht(5) and
7659 * encryption type(104) and switching encryption type to 40*/
7660 pWextState->roamProfile.EncryptionType.
7661 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7662 pWextState->roamProfile.mcEncryptionType.
7663 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7664 }
7665
7666 setKey.encType =
7667 pWextState->roamProfile.EncryptionType.
7668 encryptionType[0];
7669
7670 /* Issue set key request */
7671 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7672 pAdapter->sessionId, &setKey,
7673 &roamId);
7674
7675 if (0 != status) {
7676 hddLog(LOGE,
7677 FL("sme_roam_set_key failed, returned %d"),
7678 status);
7679 return -EINVAL;
7680 }
7681 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007682 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007683 /* In SoftAp mode setting key direction for default mode */
7684 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7685 pWextState->roamProfile.EncryptionType.encryptionType[0])
7686 && (eCSR_ENCRYPT_TYPE_AES !=
7687 pWextState->roamProfile.EncryptionType.
7688 encryptionType[0])) {
7689 /* Saving key direction for default key index to TX default */
7690 hdd_ap_ctx_t *pAPCtx =
7691 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7692 pAPCtx->wepKey[key_index].keyDirection =
7693 eSIR_TX_DEFAULT;
7694 }
7695 }
7696
7697 EXIT();
7698 return status;
7699}
7700
7701static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7702 struct net_device *ndev,
7703 u8 key_index,
7704 bool unicast, bool multicast)
7705{
7706 int ret;
7707 cds_ssr_protect(__func__);
7708 ret =
7709 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
7710 multicast);
7711 cds_ssr_unprotect(__func__);
7712
7713 return ret;
7714}
7715
7716/**
7717 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
7718 * @pAdapter: Pointer to adapter
7719 * @pRoamInfo: Pointer to roam info
7720 *
7721 * Return: struct cfg80211_bss pointer
7722 */
7723struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
7724 tCsrRoamInfo *pRoamInfo)
7725{
7726 struct net_device *dev = pAdapter->dev;
7727 struct wireless_dev *wdev = dev->ieee80211_ptr;
7728 struct wiphy *wiphy = wdev->wiphy;
7729 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
7730 int chan_no;
7731 unsigned int freq;
7732 struct ieee80211_channel *chan;
7733 struct cfg80211_bss *bss = NULL;
7734
7735 ENTER();
7736
7737 if (NULL == pBssDesc) {
7738 hddLog(LOGE, FL("pBssDesc is NULL"));
7739 return bss;
7740 }
7741
7742 if (NULL == pRoamInfo->pProfile) {
7743 hddLog(LOGE, FL("Roam profile is NULL"));
7744 return bss;
7745 }
7746
7747 chan_no = pBssDesc->channelId;
7748
7749 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
7750 freq =
7751 ieee80211_channel_to_frequency(chan_no,
7752 IEEE80211_BAND_2GHZ);
7753 } else {
7754 freq =
7755 ieee80211_channel_to_frequency(chan_no,
7756 IEEE80211_BAND_5GHZ);
7757 }
7758
7759 chan = __ieee80211_get_channel(wiphy, freq);
7760
7761 if (!chan) {
7762 hddLog(LOGE, FL("chan pointer is NULL"));
7763 return NULL;
7764 }
7765
7766 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
7767 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
7768 ssId[0],
7769 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
Ryan Hsu535d16a2016-01-18 16:45:12 -08007770#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007771 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
Ryan Hsu535d16a2016-01-18 16:45:12 -08007772#else
7773 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
7774#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007775 if (bss == NULL) {
7776 hddLog(LOGE, FL("BSS not present"));
7777 } else {
7778 hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID "
7779 MAC_ADDRESS_STR),
7780 MAC_ADDR_ARRAY(pBssDesc->bssId));
7781 cfg80211_unlink_bss(wiphy, bss);
7782 }
7783 return bss;
7784}
7785
7786/**
7787 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
7788 * @pAdapter: Pointer to adapter
7789 * @bss_desc: Pointer to bss descriptor
7790 *
7791 * This function is used to inform the BSS details to nl80211 interface.
7792 *
7793 * Return: struct cfg80211_bss pointer
7794 */
7795static struct cfg80211_bss *
7796wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
7797 tSirBssDescription *bss_desc)
7798{
7799 /*
7800 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
7801 * already exists in bss data base of cfg80211 for that particular BSS
7802 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
7803 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
7804 * As of now there is no possibility to get the mgmt(probe response)
7805 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
7806 * and passing to cfg80211_inform_bss_frame.
7807 */
7808 struct net_device *dev = pAdapter->dev;
7809 struct wireless_dev *wdev = dev->ieee80211_ptr;
7810 struct wiphy *wiphy = wdev->wiphy;
7811 int chan_no = bss_desc->channelId;
7812#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7813 qcom_ie_age *qie_age = NULL;
7814 int ie_length =
7815 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
7816#else
7817 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
7818#endif
7819 const char *ie =
7820 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
7821 unsigned int freq;
7822 struct ieee80211_channel *chan;
7823 struct ieee80211_mgmt *mgmt = NULL;
7824 struct cfg80211_bss *bss_status = NULL;
7825 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
7826 int rssi = 0;
7827 hdd_context_t *pHddCtx;
7828 int status;
7829#ifdef CONFIG_CNSS
7830 struct timespec ts;
7831#endif
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007832 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007833
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307834 ENTER();
7835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007836 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7837 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307838 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007839 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007840
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007841 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007842 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
7843 if (!mgmt) {
7844 hddLog(LOGE, FL("memory allocation failed"));
7845 return NULL;
7846 }
7847
7848 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
7849
7850#ifdef CONFIG_CNSS
7851 /* Android does not want the timestamp from the frame.
7852 Instead it wants a monotonic increasing value */
7853 cnss_get_monotonic_boottime(&ts);
7854 mgmt->u.probe_resp.timestamp =
7855 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
7856#else
7857 /* keep old behavior for non-open source (for now) */
7858 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
7859 sizeof(bss_desc->timeStamp));
7860
7861#endif
7862
7863 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
7864 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
7865
7866#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7867 /* GPS Requirement: need age ie per entry. Using vendor specific. */
7868 /* Assuming this is the last IE, copy at the end */
7869 ie_length -= sizeof(qcom_ie_age);
7870 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
7871 qie_age->element_id = QCOM_VENDOR_IE_ID;
7872 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
7873 qie_age->oui_1 = QCOM_OUI1;
7874 qie_age->oui_2 = QCOM_OUI2;
7875 qie_age->oui_3 = QCOM_OUI3;
7876 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
7877 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +05307878 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007879 qie_age->tsf_delta = bss_desc->tsf_delta;
7880#endif
7881
7882 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
7883 if (bss_desc->fProbeRsp) {
7884 mgmt->frame_control |=
7885 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
7886 } else {
7887 mgmt->frame_control |=
7888 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
7889 }
7890
7891 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
7892 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
7893 freq =
7894 ieee80211_channel_to_frequency(chan_no,
7895 IEEE80211_BAND_2GHZ);
7896 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
7897 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
7898 freq =
7899 ieee80211_channel_to_frequency(chan_no,
7900 IEEE80211_BAND_5GHZ);
7901 } else {
7902 hddLog(LOGE, FL("Invalid chan_no %d"), chan_no);
7903 kfree(mgmt);
7904 return NULL;
7905 }
7906
7907 chan = __ieee80211_get_channel(wiphy, freq);
7908 /* When the band is changed on the fly using the GUI, three things are done
7909 * 1. scan abort
7910 * 2. flush scan results from cache
7911 * 3. update the band with the new band user specified (refer to the
7912 * hdd_set_band_helper function) as part of the scan abort, message will be
7913 * queued to PE and we proceed with flushing and changinh the band.
7914 * PE will stop the scanning further and report back the results what ever
7915 * it had till now by calling the call back function.
7916 * if the time between update band and scandone call back is sufficient
7917 * enough the band change reflects in SME, SME validates the channels
7918 * and discards the channels correponding to previous band and calls back
7919 * with zero bss results. but if the time between band update and scan done
7920 * callback is very small then band change will not reflect in SME and SME
7921 * reports to HDD all the channels correponding to previous band.this is due
7922 * to race condition.but those channels are invalid to the new band and so
7923 * this function __ieee80211_get_channel will return NULL.Each time we
7924 * report scan result with this pointer null warning kernel trace is printed.
7925 * if the scan results contain large number of APs continuosly kernel
7926 * warning trace is printed and it will lead to apps watch dog bark.
7927 * So drop the bss and continue to next bss.
7928 */
7929 if (chan == NULL) {
7930 hddLog(LOGE, FL("chan pointer is NULL"));
7931 kfree(mgmt);
7932 return NULL;
7933 }
7934
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007935 /* Based on .ini configuration, raw rssi can be reported for bss.
7936 * Raw rssi is typically used for estimating power.
7937 */
7938
7939 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
7940 bss_desc->rssi;
7941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007942 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +05307943 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007944
7945 hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"),
7946 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
7947 (int)(rssi / 100));
7948
7949 bss_status =
7950 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
7951 GFP_KERNEL);
7952 kfree(mgmt);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307953 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007954 return bss_status;
7955}
7956
7957/**
7958 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
7959 * @pAdapter: Pointer to adapter
7960 * @pRoamInfo: Pointer to roam info
7961 *
7962 * This function is used to update the BSS data base of CFG8011
7963 *
7964 * Return: struct cfg80211_bss pointer
7965 */
7966struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
7967 tCsrRoamInfo *pRoamInfo)
7968{
7969 tCsrRoamConnectedProfile roamProfile;
7970 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7971 struct cfg80211_bss *bss = NULL;
7972
7973 ENTER();
7974
7975 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
7976 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
7977
7978 if (NULL != roamProfile.pBssDesc) {
7979 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7980 roamProfile.pBssDesc);
7981
7982 if (NULL == bss)
7983 hddLog(LOG1,
7984 FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL"));
7985
Naveen Rawatdf0a7e72016-01-06 18:35:53 -08007986 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007987 } else {
7988 hddLog(LOGE, FL("roamProfile.pBssDesc is NULL"));
7989 }
7990 EXIT();
7991 return bss;
7992}
7993/**
7994 * wlan_hdd_cfg80211_update_bss() - update bss
7995 * @wiphy: Pointer to wiphy
7996 * @pAdapter: Pointer to adapter
7997 * @scan_time: scan request timestamp
7998 *
7999 * Return: zero if success, non-zero otherwise
8000 */
8001int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
8002 hdd_adapter_t *pAdapter,
8003 uint32_t scan_time)
8004{
8005 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8006 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308007 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008008 tScanResultHandle pResult;
8009 struct cfg80211_bss *bss_status = NULL;
8010 hdd_context_t *pHddCtx;
8011 int ret;
8012
8013 ENTER();
8014
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308015 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008016 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
8017 NO_SESSION, pAdapter->sessionId));
8018
8019 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8020 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308021 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008022 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008023
8024 /* start getting scan results and populate cgf80211 BSS database */
8025 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
8026
8027 /* no scan results */
8028 if (NULL == pResult) {
8029 hddLog(LOGE, FL("No scan result Status %d"), status);
8030 return status;
8031 }
8032
8033 pScanResult = sme_scan_result_get_first(hHal, pResult);
8034
8035 while (pScanResult) {
8036 /*
8037 * - cfg80211_inform_bss() is not updating ie field of bss
8038 * entry if entry already exists in bss data base of cfg80211
8039 * for that particular BSS ID. Using cfg80211_inform_bss_frame
8040 * to update thebss entry instead of cfg80211_inform_bss,
8041 * But this call expects mgmt packet as input. As of now
8042 * there is no possibility to get the mgmt(probe response)
8043 * frame from PE, converting bss_desc to
8044 * ieee80211_mgmt(probe response) and passing to c
8045 * fg80211_inform_bss_frame.
8046 * - Update BSS only if beacon timestamp is later than
8047 * scan request timestamp.
8048 */
8049 if ((scan_time == 0) ||
8050 (scan_time <
8051 pScanResult->BssDescriptor.nReceivedTime)) {
8052 bss_status =
8053 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
8054 &pScanResult->BssDescriptor);
8055
8056 if (NULL == bss_status) {
8057 hdd_info("NULL returned by cfg80211_inform_bss_frame");
8058 } else {
8059 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008060 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008061 bss_status);
8062 }
8063 } else {
8064 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
8065 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
8066 }
8067 pScanResult = sme_scan_result_get_next(hHal, pResult);
8068 }
8069
8070 sme_scan_result_purge(hHal, pResult);
8071 /*
8072 * For SAP mode, scan is invoked by hostapd during SAP start
8073 * if hostapd is restarted, we need to flush previous scan
8074 * result so that it will reflect environment change
8075 */
Krunal Sonib4326f22016-03-10 13:05:51 -08008076 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008077#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
8078 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
8079#endif
8080 )
8081 sme_scan_flush_result(hHal);
8082
8083 EXIT();
8084 return 0;
8085}
8086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008087/**
8088 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
8089 * @pAdapter: Pointer to adapter
8090 * @pRoamInfo: Pointer to roam info
8091 * @index: Index
8092 * @preauth: Preauth flag
8093 *
8094 * This function is used to notify the supplicant of a new PMKSA candidate.
8095 *
8096 * Return: 0 for success, non-zero for failure
8097 */
8098int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
8099 tCsrRoamInfo *pRoamInfo,
8100 int index, bool preauth)
8101{
8102#ifdef FEATURE_WLAN_OKC
8103 struct net_device *dev = pAdapter->dev;
8104 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
8105
8106 ENTER();
8107 hddLog(LOG1, FL("is going to notify supplicant of:"));
8108
8109 if (NULL == pRoamInfo) {
8110 hddLog(LOGP, FL("pRoamInfo is NULL"));
8111 return -EINVAL;
8112 }
8113
8114 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
8115 hddLog(LOG1, MAC_ADDRESS_STR,
8116 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
8117 cfg80211_pmksa_candidate_notify(dev, index,
8118 pRoamInfo->bssid.bytes,
8119 preauth, GFP_KERNEL);
8120 }
8121#endif /* FEATURE_WLAN_OKC */
8122 return 0;
8123}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008124
8125#ifdef FEATURE_WLAN_LFR_METRICS
8126/**
8127 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
8128 * @pAdapter: Pointer to adapter
8129 * @pRoamInfo: Pointer to roam info
8130 *
8131 * 802.11r/LFR metrics reporting function to report preauth initiation
8132 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308133 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008134 */
8135#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308136QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008137 tCsrRoamInfo *pRoamInfo)
8138{
8139 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8140 union iwreq_data wrqu;
8141
8142 ENTER();
8143
8144 if (NULL == pAdapter) {
8145 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308146 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008147 }
8148
8149 /* create the event */
8150 memset(&wrqu, 0, sizeof(wrqu));
8151 memset(metrics_notification, 0, sizeof(metrics_notification));
8152
8153 wrqu.data.pointer = metrics_notification;
8154 wrqu.data.length = scnprintf(metrics_notification,
8155 sizeof(metrics_notification),
8156 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
8157 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8158
8159 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
8160 metrics_notification);
8161
8162 EXIT();
8163
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308164 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008165}
8166
8167/**
8168 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
8169 * @pAdapter: Pointer to adapter
8170 * @pRoamInfo: Pointer to roam info
8171 * @preauth_status: Preauth status
8172 *
8173 * 802.11r/LFR metrics reporting function to report handover initiation
8174 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308175 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008176 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308177QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
8179 tCsrRoamInfo *pRoamInfo,
8180 bool preauth_status)
8181{
8182 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8183 union iwreq_data wrqu;
8184
8185 ENTER();
8186
8187 if (NULL == pAdapter) {
8188 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308189 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008190 }
8191
8192 /* create the event */
8193 memset(&wrqu, 0, sizeof(wrqu));
8194 memset(metrics_notification, 0, sizeof(metrics_notification));
8195
8196 scnprintf(metrics_notification, sizeof(metrics_notification),
8197 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
8198 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8199
8200 if (1 == preauth_status)
8201 strlcat(metrics_notification, " true",
8202 sizeof(metrics_notification));
8203 else
8204 strlcat(metrics_notification, " false",
8205 sizeof(metrics_notification));
8206
8207 wrqu.data.pointer = metrics_notification;
8208 wrqu.data.length = strlen(metrics_notification);
8209
8210 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
8211 metrics_notification);
8212
8213 EXIT();
8214
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308215 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008216}
8217
8218/**
8219 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
8220 * @pAdapter: Pointer to adapter
8221 * @pRoamInfo: Pointer to roam info
8222 *
8223 * 802.11r/LFR metrics reporting function to report handover initiation
8224 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308225 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008226 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308227QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008228 tCsrRoamInfo *pRoamInfo)
8229{
8230 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8231 union iwreq_data wrqu;
8232
8233 ENTER();
8234
8235 if (NULL == pAdapter) {
8236 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308237 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008238 }
8239
8240 /* create the event */
8241 memset(&wrqu, 0, sizeof(wrqu));
8242 memset(metrics_notification, 0, sizeof(metrics_notification));
8243
8244 wrqu.data.pointer = metrics_notification;
8245 wrqu.data.length = scnprintf(metrics_notification,
8246 sizeof(metrics_notification),
8247 "QCOM: LFR_PREAUTH_HANDOVER "
8248 MAC_ADDRESS_STR,
8249 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8250
8251 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
8252 metrics_notification);
8253
8254 EXIT();
8255
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308256 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008257}
8258#endif
8259
8260/**
8261 * hdd_select_cbmode() - select channel bonding mode
8262 * @pAdapter: Pointer to adapter
8263 * @operatingChannel: Operating channel
8264 *
8265 * Return: none
8266 */
8267void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel)
8268{
8269 uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
8270 eHddDot11Mode hddDot11Mode = iniDot11Mode;
Amar Singhale4f28ee2015-10-21 14:36:56 -07008271 struct ch_params_s ch_params;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008272 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8273 uint32_t cb_mode;
8274 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
8275
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008276 ch_params.ch_width =
8277 (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth;
8278
8279 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode);
8280 switch (iniDot11Mode) {
8281 case eHDD_DOT11_MODE_AUTO:
8282 case eHDD_DOT11_MODE_11ac:
8283 case eHDD_DOT11_MODE_11ac_ONLY:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008284 if (sme_is_feature_supported_by_fw(DOT11AC))
8285 hddDot11Mode = eHDD_DOT11_MODE_11ac;
8286 else
8287 hddDot11Mode = eHDD_DOT11_MODE_11n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008288 break;
8289 case eHDD_DOT11_MODE_11n:
8290 case eHDD_DOT11_MODE_11n_ONLY:
8291 hddDot11Mode = eHDD_DOT11_MODE_11n;
8292 break;
8293 default:
8294 hddDot11Mode = iniDot11Mode;
8295 break;
8296 }
8297 /* This call decides required channel bonding mode */
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008298 cb_mode = sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008299 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
8300 operationChannel, 0,
8301 &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008302
8303 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
8304 ch_info->channel_width = ch_params.ch_width;
8305 ch_info->phy_mode = hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode);
8306 ch_info->channel = operationChannel;
8307 ch_info->cb_mode = cb_mode;
8308 hdd_info("ch_info width %d, phymode %d channel %d",
8309 ch_info->channel_width, ch_info->phy_mode,
8310 ch_info->channel);
8311 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008312}
8313
Rajeev Kumar249ea8d2016-04-15 16:57:46 -07008314/**
8315 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
8316 * @adapter: STA adapter
8317 * @roam_profile: STA roam profile
8318 *
8319 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
8320 *
8321 * Return: false if sta-sap conc is not allowed, else return true
8322 */
8323static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
8324 tCsrRoamProfile *roam_profile)
8325{
8326 hdd_context_t *hdd_ctx;
8327 hdd_adapter_t *ap_adapter;
8328 hdd_ap_ctx_t *hdd_ap_ctx;
8329 hdd_hostapd_state_t *hostapd_state;
8330 uint8_t channel = 0;
8331 QDF_STATUS status;
8332
8333 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8334 if (!hdd_ctx) {
8335 hdd_err("HDD context is NULL");
8336 return true;
8337 }
8338
8339 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
8340 /* probably no sap running, no handling required */
8341 if (ap_adapter == NULL)
8342 return true;
8343
8344 /*
8345 * sap is not in started state, so it is fine to go ahead with sta.
8346 * if sap is currently doing CAC then don't allow sta to go further.
8347 */
8348 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
8349 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
8350 return true;
8351
8352 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
8353 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
8354 return false;
8355 }
8356
8357 /*
8358 * log and return error, if we allow STA to go through, we don't
8359 * know what is going to happen better stop sta connection
8360 */
8361 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8362 if (NULL == hdd_ap_ctx) {
8363 hdd_err("AP context not found");
8364 return false;
8365 }
8366
8367 /* sap is on non-dfs channel, nothing to handle */
8368 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
8369 hdd_info("sap is on non-dfs channel, sta is allowed");
8370 return true;
8371 }
8372 /*
8373 * find out by looking in to scan cache where sta is going to
8374 * connect by passing its roam_profile. if channel is 0 or DFS then
8375 * better to call pcl and find out the best channel. if channel
8376 * is non-dfs then better move SAP to STA's channel to make
8377 * scc, so we have room for 3port MCC scenario
8378 */
8379 status = cds_get_channel_from_scan_result(adapter,
8380 roam_profile, &channel);
8381
8382 if ((QDF_STATUS_SUCCESS != status) || (0 == channel) ||
8383 CDS_IS_DFS_CH(channel))
8384 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
8385 true);
8386
8387 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8388 qdf_event_reset(&hostapd_state->qdf_event);
8389 status = wlansap_set_channel_change_with_csa(
8390 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
8391 hdd_ap_ctx->sapConfig.ch_width_orig);
8392
8393 if (QDF_STATUS_SUCCESS != status) {
8394 hdd_err("Set channel with CSA IE failed, can't allow STA");
8395 return false;
8396 }
8397
8398 /*
8399 * wait here for SAP to finish the channel switch. When channel
8400 * switch happens, SAP sends few beacons with CSA_IE. After
8401 * successfully Transmission of those beacons, it will move its
8402 * state from started to disconnected and move to new channel.
8403 * once it moves to new channel, sap again moves its state
8404 * machine from disconnected to started and set this event.
8405 * wait for 10 secs to finish this.
8406 */
8407 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
8408 if (!QDF_IS_STATUS_SUCCESS(status)) {
8409 hdd_err("wait for qdf_event failed, STA not allowed!!");
8410 return false;
8411 }
8412
8413 return true;
8414}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008415
8416/*
8417 * FUNCTION: wlan_hdd_cfg80211_connect_start
8418 * wlan_hdd_cfg80211_connect_start() - start connection
8419 * @pAdapter: Pointer to adapter
8420 * @ssid: Pointer ot ssid
8421 * @ssid_len: Length of ssid
8422 * @bssid: Pointer to bssid
8423 * @operatingChannel: Operating channel
8424 *
8425 * This function is used to start the association process
8426 *
8427 * Return: 0 for success, non-zero for failure
8428 */
8429int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
8430 const u8 *ssid, size_t ssid_len,
8431 const u8 *bssid_hint, const u8 *bssid,
8432 u8 operatingChannel)
8433{
8434 int status = 0;
8435 hdd_wext_state_t *pWextState;
8436 hdd_context_t *pHddCtx;
8437 uint32_t roamId;
8438 tCsrRoamProfile *pRoamProfile;
8439 eCsrAuthType RSNAuthType;
8440 tSmeConfigParams *sme_config;
8441
8442 ENTER();
8443
8444 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8445 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8446
8447 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308448 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008449 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008450
8451 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
8452 hddLog(LOGE, FL("wrong SSID len"));
8453 return -EINVAL;
8454 }
8455
8456 pRoamProfile = &pWextState->roamProfile;
8457
8458 if (pRoamProfile) {
8459 hdd_station_ctx_t *pHddStaCtx;
8460 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8461
8462 if (HDD_WMM_USER_MODE_NO_QOS ==
8463 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
8464 /*QoS not enabled in cfg file */
8465 pRoamProfile->uapsd_mask = 0;
8466 } else {
8467 /*QoS enabled, update uapsd mask from cfg file */
8468 pRoamProfile->uapsd_mask =
8469 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
8470 }
8471
8472 pRoamProfile->SSIDs.numOfSSIDs = 1;
8473 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308474 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008475 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308476 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008477 ssid, ssid_len);
8478
8479 if (bssid) {
8480 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308481 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308482 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008483 /* Save BSSID in seperate variable as well, as RoamProfile
8484 BSSID is getting zeroed out in the association process. And in
8485 case of join failure we should send valid BSSID to supplicant
8486 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308487 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308488 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008489 } else if (bssid_hint) {
8490 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308491 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308492 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008493 /* Save BSSID in separate variable as well, as
8494 RoamProfile BSSID is getting zeroed out in the
8495 association process. And in case of join failure
8496 we should send valid BSSID to supplicant
8497 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308498 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308499 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008500 hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR),
8501 MAC_ADDR_ARRAY(bssid_hint));
8502 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308503 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308504 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008505 }
8506
8507 hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"),
8508 pRoamProfile->SSIDs.SSIDList->SSID.length,
8509 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
8510 operatingChannel);
8511
8512 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
8513 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
8514 /*set gen ie */
8515 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
8516 /*set auth */
8517 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
8518 }
8519#ifdef FEATURE_WLAN_WAPI
8520 if (pAdapter->wapi_info.nWapiMode) {
8521 hddLog(LOG1,
8522 FL("Setting WAPI AUTH Type and Encryption Mode values"));
8523 switch (pAdapter->wapi_info.wapiAuthMode) {
8524 case WAPI_AUTH_MODE_PSK:
8525 {
8526 hddLog(LOG1,
8527 FL("WAPI AUTH TYPE: PSK: %d"),
8528 pAdapter->wapi_info.wapiAuthMode);
8529 pRoamProfile->AuthType.authType[0] =
8530 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
8531 break;
8532 }
8533 case WAPI_AUTH_MODE_CERT:
8534 {
8535 hddLog(LOG1,
8536 FL("WAPI AUTH TYPE: CERT: %d"),
8537 pAdapter->wapi_info.wapiAuthMode);
8538 pRoamProfile->AuthType.authType[0] =
8539 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
8540 break;
8541 }
8542 } /* End of switch */
8543 if (pAdapter->wapi_info.wapiAuthMode ==
8544 WAPI_AUTH_MODE_PSK
8545 || pAdapter->wapi_info.wapiAuthMode ==
8546 WAPI_AUTH_MODE_CERT) {
8547 hddLog(LOG1,
8548 FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI"));
8549 pRoamProfile->AuthType.numEntries = 1;
8550 pRoamProfile->EncryptionType.numEntries = 1;
8551 pRoamProfile->EncryptionType.encryptionType[0] =
8552 eCSR_ENCRYPT_TYPE_WPI;
8553 pRoamProfile->mcEncryptionType.numEntries = 1;
8554 pRoamProfile->mcEncryptionType.
8555 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
8556 }
8557 }
8558#endif /* FEATURE_WLAN_WAPI */
8559#ifdef WLAN_FEATURE_GTK_OFFLOAD
8560 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -08008561 if ((QDF_STA_MODE == pAdapter->device_mode) ||
8562 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
8564 sizeof(tSirGtkOffloadParams));
8565 pHddStaCtx->gtkOffloadReqParams.ulFlags =
8566 GTK_OFFLOAD_DISABLE;
8567 }
8568#endif
8569 pRoamProfile->csrPersona = pAdapter->device_mode;
8570
8571 if (operatingChannel) {
8572 pRoamProfile->ChannelInfo.ChannelList =
8573 &operatingChannel;
8574 pRoamProfile->ChannelInfo.numOfChannels = 1;
8575 } else {
8576 pRoamProfile->ChannelInfo.ChannelList = NULL;
8577 pRoamProfile->ChannelInfo.numOfChannels = 0;
8578 }
Krunal Sonib4326f22016-03-10 13:05:51 -08008579 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008580 && operatingChannel) {
8581 /*
8582 * Need to post the IBSS power save parameters
8583 * to WMA. WMA will configure this parameters
8584 * to firmware if power save is enabled by the
8585 * firmware.
8586 */
8587 status = hdd_set_ibss_power_save_params(pAdapter);
8588
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308589 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008590 hddLog(LOGE,
8591 FL("Set IBSS Power Save Params Failed"));
8592 return -EINVAL;
8593 }
8594 hdd_select_cbmode(pAdapter, operatingChannel);
8595 }
8596
8597 if (pHddCtx->config->policy_manager_enabled &&
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008598 (true == cds_is_connection_in_progress())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008599 hdd_err("Connection refused: conn in progress");
8600 return -EINVAL;
8601 }
8602
8603 /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect()
8604 * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state
8605 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
8606 * by either hdd_association_completion_handler() or hdd_dis_connect_handler() in sme_RoamCallback()
8607 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
8608 */
Krunal Sonib4326f22016-03-10 13:05:51 -08008609 if (QDF_STA_MODE == pAdapter->device_mode ||
8610 QDF_P2P_CLIENT_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008611 hddLog(LOG1,
8612 FL("Set HDD connState to eConnectionState_Connecting"));
8613 hdd_conn_set_connection_state(pAdapter,
8614 eConnectionState_Connecting);
8615 }
8616
8617 /* After 8-way handshake supplicant should give the scan command
8618 * in that it update the additional IEs, But because of scan
8619 * enhancements, the supplicant is not issuing the scan command now.
8620 * So the unicast frames which are sent from the host are not having
8621 * the additional IEs. If it is P2P CLIENT and there is no additional
8622 * IE present in roamProfile, then use the addtional IE form scan_info
8623 */
8624
Krunal Sonib4326f22016-03-10 13:05:51 -08008625 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008626 (!pRoamProfile->pAddIEScan)) {
8627 pRoamProfile->pAddIEScan =
8628 &pAdapter->scan_info.scanAddIE.addIEdata[0];
8629 pRoamProfile->nAddIEScanLength =
8630 pAdapter->scan_info.scanAddIE.length;
8631 }
8632 /*
8633 * When policy manager is enabled from ini file, we shouldn't
8634 * check for other concurrency rules.
8635 */
8636 if (!pHddCtx->config->policy_manager_enabled) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008637 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008638 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008639 pAdapter, pRoamProfile, &roamId))
8640 return 0;
8641 }
8642
Rajeev Kumar249ea8d2016-04-15 16:57:46 -07008643 if (pHddCtx->config->policy_manager_enabled &&
8644 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
8645 pRoamProfile))) {
8646 hdd_err("sap-sta conc will fail, can't allow sta");
8647 hdd_conn_set_connection_state(pAdapter,
8648 eConnectionState_NotConnected);
8649 return -ENOMEM;
8650 }
8651
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308652 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008653 if (!sme_config) {
8654 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -07008655 hdd_conn_set_connection_state(pAdapter,
8656 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008657 return -ENOMEM;
8658 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308659 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008660 sme_get_config_param(pHddCtx->hHal, sme_config);
8661 /* These values are not sessionized. So, any change in these SME
8662 * configs on an older or parallel interface will affect the
8663 * cb mode. So, restoring the default INI params before starting
8664 * interfaces such as sta, cli etc.,
8665 */
8666 sme_config->csrConfig.channelBondingMode5GHz =
8667 pHddCtx->config->nChannelBondingMode5GHz;
8668 sme_config->csrConfig.channelBondingMode24GHz =
8669 pHddCtx->config->nChannelBondingMode24GHz;
8670 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308671 qdf_mem_free(sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008672
8673 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8674 pAdapter->sessionId, pRoamProfile,
8675 &roamId);
8676
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308677 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08008678 (QDF_STA_MODE == pAdapter->device_mode ||
8679 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008680 hddLog(LOGE,
8681 FL("sme_roam_connect (session %d) failed with "
8682 "status %d. -> NotConnected"),
8683 pAdapter->sessionId, status);
8684 /* change back to NotAssociated */
8685 hdd_conn_set_connection_state(pAdapter,
8686 eConnectionState_NotConnected);
8687 }
8688
8689 pRoamProfile->ChannelInfo.ChannelList = NULL;
8690 pRoamProfile->ChannelInfo.numOfChannels = 0;
8691
8692 } else {
8693 hddLog(LOGE, FL("No valid Roam profile"));
8694 return -EINVAL;
8695 }
8696 EXIT();
8697 return status;
8698}
8699
8700/**
8701 * wlan_hdd_cfg80211_set_auth_type() - set auth type
8702 * @pAdapter: Pointer to adapter
8703 * @auth_type: Auth type
8704 *
8705 * This function is used to set the authentication type (OPEN/SHARED).
8706 *
8707 * Return: 0 for success, non-zero for failure
8708 */
8709static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
8710 enum nl80211_auth_type auth_type)
8711{
8712 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8713 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8714
8715 ENTER();
8716
8717 /*set authentication type */
8718 switch (auth_type) {
8719 case NL80211_AUTHTYPE_AUTOMATIC:
8720 hddLog(LOG1,
8721 FL("set authentication type to AUTOSWITCH"));
8722 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
8723 break;
8724
8725 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726 case NL80211_AUTHTYPE_FT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008727 hddLog(LOG1,
8728 FL("set authentication type to OPEN"));
8729 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8730 break;
8731
8732 case NL80211_AUTHTYPE_SHARED_KEY:
8733 hddLog(LOG1,
8734 FL("set authentication type to SHARED"));
8735 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
8736 break;
8737#ifdef FEATURE_WLAN_ESE
8738 case NL80211_AUTHTYPE_NETWORK_EAP:
8739 hddLog(LOG1,
8740 FL("set authentication type to CCKM WPA"));
8741 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
8742 break;
8743#endif
8744
8745 default:
8746 hddLog(LOGE,
8747 FL("Unsupported authentication type %d"), auth_type);
8748 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
8749 return -EINVAL;
8750 }
8751
8752 pWextState->roamProfile.AuthType.authType[0] =
8753 pHddStaCtx->conn_info.authType;
8754 return 0;
8755}
8756
8757/**
8758 * wlan_hdd_set_akm_suite() - set key management type
8759 * @pAdapter: Pointer to adapter
8760 * @key_mgmt: Key management type
8761 *
8762 * This function is used to set the key mgmt type(PSK/8021x).
8763 *
8764 * Return: 0 for success, non-zero for failure
8765 */
8766static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
8767{
8768 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8769
8770 ENTER();
8771
8772#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
8773#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
8774 /*set key mgmt type */
8775 switch (key_mgmt) {
8776 case WLAN_AKM_SUITE_PSK:
8777 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008778 case WLAN_AKM_SUITE_FT_PSK:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008779 hddLog(LOG1, FL("setting key mgmt type to PSK"));
8780 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
8781 break;
8782
8783 case WLAN_AKM_SUITE_8021X_SHA256:
8784 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008785 case WLAN_AKM_SUITE_FT_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008786 hddLog(LOG1,
8787 FL("setting key mgmt type to 8021x"));
8788 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8789 break;
8790#ifdef FEATURE_WLAN_ESE
8791#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
8792#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
8793 case WLAN_AKM_SUITE_CCKM:
8794 hddLog(LOG1,
8795 FL("setting key mgmt type to CCKM"));
8796 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
8797 break;
8798#endif
8799#ifndef WLAN_AKM_SUITE_OSEN
8800#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
8801#endif
8802 case WLAN_AKM_SUITE_OSEN:
8803 hddLog(LOG1,
8804 FL("setting key mgmt type to OSEN"));
8805 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8806 break;
8807
8808 default:
8809 hddLog(LOGE,
8810 FL("Unsupported key mgmt type %d"), key_mgmt);
8811 return -EINVAL;
8812
8813 }
8814 return 0;
8815}
8816
8817/**
8818 * wlan_hdd_cfg80211_set_cipher() - set encryption type
8819 * @pAdapter: Pointer to adapter
8820 * @cipher: Cipher type
8821 * @ucast: Unicast flag
8822 *
8823 * This function is used to set the encryption type
8824 * (NONE/WEP40/WEP104/TKIP/CCMP).
8825 *
8826 * Return: 0 for success, non-zero for failure
8827 */
8828static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
8829 u32 cipher, bool ucast)
8830{
8831 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8832 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8833 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8834
8835 ENTER();
8836
8837 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008838 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008839 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8840 } else {
8841
8842 /*set encryption method */
8843 switch (cipher) {
8844 case IW_AUTH_CIPHER_NONE:
8845 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8846 break;
8847
8848 case WLAN_CIPHER_SUITE_WEP40:
8849 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
8850 break;
8851
8852 case WLAN_CIPHER_SUITE_WEP104:
8853 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
8854 break;
8855
8856 case WLAN_CIPHER_SUITE_TKIP:
8857 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
8858 break;
8859
8860 case WLAN_CIPHER_SUITE_CCMP:
8861 encryptionType = eCSR_ENCRYPT_TYPE_AES;
8862 break;
8863#ifdef FEATURE_WLAN_WAPI
8864 case WLAN_CIPHER_SUITE_SMS4:
8865 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
8866 break;
8867#endif
8868
8869#ifdef FEATURE_WLAN_ESE
8870 case WLAN_CIPHER_SUITE_KRK:
8871 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
8872 break;
8873#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8874 case WLAN_CIPHER_SUITE_BTK:
8875 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
8876 break;
8877#endif
8878#endif
8879 default:
8880 hddLog(LOGE,
8881 FL("Unsupported cipher type %d"), cipher);
8882 return -EOPNOTSUPP;
8883 }
8884 }
8885
8886 if (ucast) {
8887 hddLog(LOG1,
8888 FL("setting unicast cipher type to %d"), encryptionType);
8889 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
8890 pWextState->roamProfile.EncryptionType.numEntries = 1;
8891 pWextState->roamProfile.EncryptionType.encryptionType[0] =
8892 encryptionType;
8893 } else {
8894 hddLog(LOG1,
8895 FL("setting mcast cipher type to %d"), encryptionType);
8896 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
8897 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
8898 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
8899 encryptionType;
8900 }
8901
8902 return 0;
8903}
8904
8905/**
8906 * wlan_hdd_cfg80211_set_ie() - set IEs
8907 * @pAdapter: Pointer to adapter
8908 * @ie: Pointer ot ie
8909 * @ie: IE length
8910 *
8911 * Return: 0 for success, non-zero for failure
8912 */
8913int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
8914 size_t ie_len)
8915{
8916 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8917 const uint8_t *genie = ie;
8918 uint16_t remLen = ie_len;
8919#ifdef FEATURE_WLAN_WAPI
8920 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
8921 u16 *tmp;
8922 uint16_t akmsuiteCount;
8923 int *akmlist;
8924#endif
8925 ENTER();
8926
8927 /* clear previous assocAddIE */
8928 pWextState->assocAddIE.length = 0;
8929 pWextState->roamProfile.bWPSAssociation = false;
8930 pWextState->roamProfile.bOSENAssociation = false;
8931
8932 while (remLen >= 2) {
8933 uint16_t eLen = 0;
8934 uint8_t elementId;
8935 elementId = *genie++;
8936 eLen = *genie++;
8937 remLen -= 2;
8938
8939 hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), elementId, eLen);
8940
8941 switch (elementId) {
8942 case DOT11F_EID_WPA:
8943 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
8944 hddLog(LOGE, FL("Invalid WPA IE"));
8945 return -EINVAL;
8946 } else if (0 ==
8947 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
8948 uint16_t curAddIELen =
8949 pWextState->assocAddIE.length;
8950 hddLog(LOG1,
8951 FL("Set WPS IE(len %d)"), eLen + 2);
8952
8953 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8954 (pWextState->assocAddIE.length + eLen)) {
8955 hddLog(LOGE,
8956 FL("Cannot accommodate assocAddIE. Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308957 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008958 return -ENOMEM;
8959 }
8960 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8961 memcpy(pWextState->assocAddIE.addIEdata +
8962 curAddIELen, genie - 2, eLen + 2);
8963 pWextState->assocAddIE.length += eLen + 2;
8964
8965 pWextState->roamProfile.bWPSAssociation = true;
8966 pWextState->roamProfile.pAddIEAssoc =
8967 pWextState->assocAddIE.addIEdata;
8968 pWextState->roamProfile.nAddIEAssocLength =
8969 pWextState->assocAddIE.length;
8970 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
8971 hddLog(LOG1,
8972 FL("Set WPA IE (len %d)"), eLen + 2);
8973 memset(pWextState->WPARSNIE, 0,
8974 MAX_WPA_RSN_IE_LEN);
8975 memcpy(pWextState->WPARSNIE, genie - 2,
8976 (eLen + 2));
8977 pWextState->roamProfile.pWPAReqIE =
8978 pWextState->WPARSNIE;
8979 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
8980 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
8981 P2P_OUI_TYPE_SIZE))) {
8982 uint16_t curAddIELen =
8983 pWextState->assocAddIE.length;
8984 hddLog(LOG1,
8985 FL("Set P2P IE(len %d)"), eLen + 2);
8986
8987 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8988 (pWextState->assocAddIE.length + eLen)) {
8989 hddLog(LOGE,
8990 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308991 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008992 return -ENOMEM;
8993 }
8994 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8995 memcpy(pWextState->assocAddIE.addIEdata +
8996 curAddIELen, genie - 2, eLen + 2);
8997 pWextState->assocAddIE.length += eLen + 2;
8998
8999 pWextState->roamProfile.pAddIEAssoc =
9000 pWextState->assocAddIE.addIEdata;
9001 pWextState->roamProfile.nAddIEAssocLength =
9002 pWextState->assocAddIE.length;
9003 }
9004#ifdef WLAN_FEATURE_WFD
9005 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
9006 WFD_OUI_TYPE_SIZE)) &&
9007 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -08009008 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009009 pAdapter->device_mode)) {
9010 uint16_t curAddIELen =
9011 pWextState->assocAddIE.length;
9012 hddLog(LOG1,
9013 FL("Set WFD IE(len %d)"), eLen + 2);
9014
9015 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9016 (pWextState->assocAddIE.length + eLen)) {
9017 hddLog(LOGE,
9018 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309019 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009020 return -ENOMEM;
9021 }
9022 /* WFD IE is saved to Additional IE ; it should
9023 * be accumulated to handle WPS IE + P2P IE +
9024 * WFD IE */
9025 memcpy(pWextState->assocAddIE.addIEdata +
9026 curAddIELen, genie - 2, eLen + 2);
9027 pWextState->assocAddIE.length += eLen + 2;
9028
9029 pWextState->roamProfile.pAddIEAssoc =
9030 pWextState->assocAddIE.addIEdata;
9031 pWextState->roamProfile.nAddIEAssocLength =
9032 pWextState->assocAddIE.length;
9033 }
9034#endif
9035 /* Appending HS 2.0 Indication Element in Assiciation Request */
9036 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
9037 HS20_OUI_TYPE_SIZE))) {
9038 uint16_t curAddIELen =
9039 pWextState->assocAddIE.length;
9040 hddLog(LOG1,
9041 FL("Set HS20 IE(len %d)"), eLen + 2);
9042
9043 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9044 (pWextState->assocAddIE.length + eLen)) {
9045 hddLog(LOGE,
9046 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309047 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009048 return -ENOMEM;
9049 }
9050 memcpy(pWextState->assocAddIE.addIEdata +
9051 curAddIELen, genie - 2, eLen + 2);
9052 pWextState->assocAddIE.length += eLen + 2;
9053
9054 pWextState->roamProfile.pAddIEAssoc =
9055 pWextState->assocAddIE.addIEdata;
9056 pWextState->roamProfile.nAddIEAssocLength =
9057 pWextState->assocAddIE.length;
9058 }
9059 /* Appending OSEN Information Element in Assiciation Request */
9060 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
9061 OSEN_OUI_TYPE_SIZE))) {
9062 uint16_t curAddIELen =
9063 pWextState->assocAddIE.length;
9064 hddLog(LOG1,
9065 FL("Set OSEN IE(len %d)"), eLen + 2);
9066
9067 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9068 (pWextState->assocAddIE.length + eLen)) {
9069 hddLog(LOGE,
9070 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309071 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009072 return -ENOMEM;
9073 }
9074 memcpy(pWextState->assocAddIE.addIEdata +
9075 curAddIELen, genie - 2, eLen + 2);
9076 pWextState->assocAddIE.length += eLen + 2;
9077
9078 pWextState->roamProfile.bOSENAssociation = true;
9079 pWextState->roamProfile.pAddIEAssoc =
9080 pWextState->assocAddIE.addIEdata;
9081 pWextState->roamProfile.nAddIEAssocLength =
9082 pWextState->assocAddIE.length;
9083 } else {
9084 uint16_t add_ie_len =
9085 pWextState->assocAddIE.length;
9086
9087 hdd_info("Set OSEN IE(len %d)", eLen + 2);
9088
9089 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9090 (pWextState->assocAddIE.length + eLen)) {
9091 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309092 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009093 return -ENOMEM;
9094 }
9095
9096 memcpy(pWextState->assocAddIE.addIEdata +
9097 add_ie_len, genie - 2, eLen + 2);
9098 pWextState->assocAddIE.length += eLen + 2;
9099
9100 pWextState->roamProfile.pAddIEAssoc =
9101 pWextState->assocAddIE.addIEdata;
9102 pWextState->roamProfile.nAddIEAssocLength =
9103 pWextState->assocAddIE.length;
9104 }
9105 break;
9106 case DOT11F_EID_RSN:
9107 hddLog(LOG1, FL("Set RSN IE(len %d)"), eLen + 2);
9108 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
9109 memcpy(pWextState->WPARSNIE, genie - 2,
9110 (eLen + 2));
9111 pWextState->roamProfile.pRSNReqIE =
9112 pWextState->WPARSNIE;
9113 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
9114 break;
9115 /*
9116 * Appending Extended Capabilities with Interworking bit set
9117 * in Assoc Req.
9118 *
9119 * In assoc req this EXT Cap will only be taken into account if
9120 * interworkingService bit is set to 1. Currently
9121 * driver is only interested in interworkingService capability
9122 * from supplicant. If in future any other EXT Cap info is
9123 * required from supplicat, it needs to be handled while
9124 * sending Assoc Req in LIM.
9125 */
9126 case DOT11F_EID_EXTCAP:
9127 {
9128 uint16_t curAddIELen =
9129 pWextState->assocAddIE.length;
9130 hddLog(LOG1,
9131 FL("Set Extended CAPS IE(len %d)"), eLen + 2);
9132
9133 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9134 (pWextState->assocAddIE.length + eLen)) {
9135 hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309136 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137 return -ENOMEM;
9138 }
9139 memcpy(pWextState->assocAddIE.addIEdata +
9140 curAddIELen, genie - 2, eLen + 2);
9141 pWextState->assocAddIE.length += eLen + 2;
9142
9143 pWextState->roamProfile.pAddIEAssoc =
9144 pWextState->assocAddIE.addIEdata;
9145 pWextState->roamProfile.nAddIEAssocLength =
9146 pWextState->assocAddIE.length;
9147 break;
9148 }
9149#ifdef FEATURE_WLAN_WAPI
9150 case WLAN_EID_WAPI:
9151 /* Setting WAPI Mode to ON=1 */
9152 pAdapter->wapi_info.nWapiMode = 1;
9153 hddLog(LOG1,
9154 FL("WAPI MODE IS %u"), pAdapter->wapi_info.nWapiMode);
9155 tmp = (u16 *) ie;
9156 tmp = tmp + 2; /* Skip element Id and Len, Version */
9157 akmsuiteCount = WPA_GET_LE16(tmp);
9158 tmp = tmp + 1;
9159 akmlist = (int *)(tmp);
9160 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
9161 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
9162 } else {
9163 hddLog(LOGE,
9164 FL("Invalid akmSuite count"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309165 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009166 return -EINVAL;
9167 }
9168
9169 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
9170 hddLog(LOG1,
9171 FL("WAPI AUTH MODE SET TO PSK"));
9172 pAdapter->wapi_info.wapiAuthMode =
9173 WAPI_AUTH_MODE_PSK;
9174 }
9175 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
9176 hddLog(LOG1,
9177 FL("WAPI AUTH MODE SET TO CERTIFICATE"));
9178 pAdapter->wapi_info.wapiAuthMode =
9179 WAPI_AUTH_MODE_CERT;
9180 }
9181 break;
9182#endif
9183 default:
9184 hddLog(LOGE,
9185 FL("Set UNKNOWN IE %X"), elementId);
9186 /* when Unknown IE is received we should break and continue
9187 * to the next IE in the buffer instead we were returning
9188 * so changing this to break */
9189 break;
9190 }
9191 genie += eLen;
9192 remLen -= eLen;
9193 }
9194 EXIT();
9195 return 0;
9196}
9197
9198/**
9199 * hdd_is_wpaie_present() - check for WPA ie
9200 * @ie: Pointer to ie
9201 * @ie_len: Ie length
9202 *
9203 * Parse the received IE to find the WPA IE
9204 *
9205 * Return: true if wpa ie is found else false
9206 */
9207static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
9208{
9209 uint8_t eLen = 0;
9210 uint16_t remLen = ie_len;
9211 uint8_t elementId = 0;
9212
9213 while (remLen >= 2) {
9214 elementId = *ie++;
9215 eLen = *ie++;
9216 remLen -= 2;
9217 if (eLen > remLen) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309218 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009219 "%s: IE length is wrong %d", __func__, eLen);
9220 return false;
9221 }
9222 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
9223 /* OUI - 0x00 0X50 0XF2
9224 * WPA Information Element - 0x01
9225 * WPA version - 0x01
9226 */
9227 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
9228 return true;
9229 }
9230 ie += eLen;
9231 remLen -= eLen;
9232 }
9233 return false;
9234}
9235
9236/**
9237 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
9238 * @pAdapter: Pointer to adapter
9239 * @req: Pointer to security parameters
9240 *
9241 * Return: 0 for success, non-zero for failure
9242 */
9243int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
9244 struct cfg80211_connect_params *req)
9245{
9246 int status = 0;
9247 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9248 ENTER();
9249
9250 /*set wpa version */
9251 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
9252
9253 if (req->crypto.wpa_versions) {
9254 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
9255 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
9256 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
9257 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9258 }
9259 }
9260
9261 hddLog(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion);
9262
9263 /*set authentication type */
9264 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
9265
9266 if (0 > status) {
9267 hddLog(LOGE, FL("failed to set authentication type "));
9268 return status;
9269 }
9270
9271 /*set key mgmt type */
9272 if (req->crypto.n_akm_suites) {
9273 status =
9274 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
9275 if (0 > status) {
9276 hddLog(LOGE, FL("failed to set akm suite"));
9277 return status;
9278 }
9279 }
9280
9281 /*set pairwise cipher type */
9282 if (req->crypto.n_ciphers_pairwise) {
9283 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
9284 req->crypto.
9285 ciphers_pairwise[0],
9286 true);
9287 if (0 > status) {
9288 hddLog(LOGE, FL("failed to set unicast cipher type"));
9289 return status;
9290 }
9291 } else {
9292 /*Reset previous cipher suite to none */
9293 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
9294 if (0 > status) {
9295 hddLog(LOGE, FL("failed to set unicast cipher type"));
9296 return status;
9297 }
9298 }
9299
9300 /*set group cipher type */
9301 status =
9302 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
9303 false);
9304
9305 if (0 > status) {
9306 hddLog(LOGE, FL("failed to set mcast cipher type"));
9307 return status;
9308 }
9309#ifdef WLAN_FEATURE_11W
9310 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
9311#endif
9312
9313 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
9314 if (req->ie_len) {
9315 status =
9316 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
9317 if (0 > status) {
9318 hddLog(LOGE, FL("failed to parse the WPA/RSN IE"));
9319 return status;
9320 }
9321 }
9322
9323 /*incase of WEP set default key information */
9324 if (req->key && req->key_len) {
9325 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
9326 || (WLAN_CIPHER_SUITE_WEP104 ==
9327 req->crypto.ciphers_pairwise[0])
9328 ) {
9329 if (IW_AUTH_KEY_MGMT_802_1X
9330 ==
9331 (pWextState->
9332 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
9333 hddLog(LOGE,
9334 FL("Dynamic WEP not supported"));
9335 return -EOPNOTSUPP;
9336 } else {
9337 u8 key_len = req->key_len;
9338 u8 key_idx = req->key_idx;
9339
9340 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
9341 key_len)
9342 && (CSR_MAX_NUM_KEY > key_idx)
9343 ) {
9344 hddLog(LOG1,
9345 FL("setting default wep key, key_idx = %hu key_len %hu"),
9346 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309347 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009348 Keys.
9349 KeyMaterial[key_idx][0],
9350 req->key, key_len);
9351 pWextState->roamProfile.Keys.
9352 KeyLength[key_idx] = (u8) key_len;
9353 pWextState->roamProfile.Keys.
9354 defaultIndex = (u8) key_idx;
9355 }
9356 }
9357 }
9358 }
9359
9360 return status;
9361}
9362
9363/**
9364 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
9365 * @pAdapter: Pointer to adapter
9366 *
9367 * This function is used to disconnect from previous connection
9368 *
9369 * Return: 0 for success, non-zero for failure
9370 */
9371static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
9372{
9373 unsigned long rc;
9374 hdd_station_ctx_t *pHddStaCtx;
9375 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309376 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377
9378 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9379
9380 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
9381
9382 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +05309383 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
9384 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
9385 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009386 hdd_conn_set_connection_state(pAdapter,
9387 eConnectionState_Disconnecting);
9388 /* Issue disconnect to CSR */
9389 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309390
9391 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9392 pAdapter->sessionId,
9393 eCSR_DISCONNECT_REASON_UNSPECIFIED);
9394 /*
9395 * Wait here instead of returning directly, this will block the
9396 * next connect command and allow processing of the scan for
9397 * ssid and the previous connect command in CSR. Else we might
9398 * hit some race conditions leading to SME and HDD out of sync.
9399 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309400 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309401 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
9402 } else if (0 != status) {
9403 hdd_err("csrRoamDisconnect failure, returned %d",
9404 (int)status);
9405 pHddStaCtx->staDebugState = status;
9406 result = -EINVAL;
9407 goto disconnected;
9408 }
9409
9410 rc = wait_for_completion_timeout(
9411 &pAdapter->disconnect_comp_var,
9412 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309413 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309414 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
9415 pAdapter->sessionId, pHddStaCtx->staDebugState);
9416 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 }
9418 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309419 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009420 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309421 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009422 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309423 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309425 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426 }
9427 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309428disconnected:
9429 hdd_info("Set HDD connState to eConnectionState_NotConnected");
9430 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
9431 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009432}
9433
9434/**
9435 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
9436 * @wiphy: Pointer to wiphy
9437 * @dev: Pointer to network device
9438 * @req: Pointer to cfg80211 connect request
9439 *
9440 * This function is used to start the association process
9441 *
9442 * Return: 0 for success, non-zero for failure
9443 */
9444static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
9445 struct net_device *ndev,
9446 struct cfg80211_connect_params *req)
9447{
9448 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05309449 u16 channel;
9450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
9451 const u8 *bssid_hint = req->bssid_hint;
9452#else
9453 const u8 *bssid_hint = NULL;
9454#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9456 hdd_context_t *pHddCtx;
9457
9458 ENTER();
9459
Anurag Chouhan6d760662016-02-20 16:05:43 +05309460 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009461 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9462 return -EINVAL;
9463 }
9464
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309465 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009466 TRACE_CODE_HDD_CFG80211_CONNECT,
9467 pAdapter->sessionId, pAdapter->device_mode));
9468 hddLog(LOG1, FL("Device_mode %s(%d)"),
9469 hdd_device_mode_to_string(pAdapter->device_mode),
9470 pAdapter->device_mode);
9471
Krunal Sonib4326f22016-03-10 13:05:51 -08009472 if (pAdapter->device_mode != QDF_STA_MODE &&
9473 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009474 hddLog(LOGE, FL("Device_mode %s(%d) is not supported"),
9475 hdd_device_mode_to_string(pAdapter->device_mode),
9476 pAdapter->device_mode);
9477 return -EINVAL;
9478 }
9479
9480 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9481 if (!pHddCtx) {
9482 hddLog(LOGE, FL("HDD context is null"));
9483 return -EINVAL;
9484 }
9485
9486 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309487 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009488 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009490 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -08009491 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009492 pAdapter->device_mode),
9493 req->channel->hw_value, HW_MODE_20_MHZ)) {
9494 hdd_err("This concurrency combination is not allowed");
9495 return -ECONNREFUSED;
9496 }
9497 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009498 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -08009499 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009500 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
9501 hdd_err("This concurrency combination is not allowed");
9502 return -ECONNREFUSED;
9503 }
9504 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009505 wlan_hdd_disable_roaming(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009506
9507 /*Try disconnecting if already in connected state */
9508 status = wlan_hdd_try_disconnect(pAdapter);
9509 if (0 > status) {
9510 hddLog(LOGE,
9511 FL("Failed to disconnect the existing connection"));
9512 return -EALREADY;
9513 }
9514
9515 /*initialise security parameters */
9516 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
9517
9518 if (0 > status) {
9519 hddLog(LOGE,
9520 FL("failed to set security params"));
9521 return status;
9522 }
9523
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05309524 if (req->channel)
9525 channel = req->channel->hw_value;
9526 else
9527 channel = 0;
9528 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
9529 req->ssid_len, req->bssid,
9530 bssid_hint, channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009531 if (0 > status) {
9532 hddLog(LOGE, FL("connect failed"));
9533 return status;
9534 }
9535 EXIT();
9536 return status;
9537}
9538
9539/**
9540 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
9541 * @wiphy: Pointer to wiphy
9542 * @dev: Pointer to network device
9543 * @req: Pointer to cfg80211 connect request
9544 *
9545 * Return: 0 for success, non-zero for failure
9546 */
9547static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
9548 struct net_device *ndev,
9549 struct cfg80211_connect_params *req)
9550{
9551 int ret;
9552 cds_ssr_protect(__func__);
9553 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
9554 cds_ssr_unprotect(__func__);
9555
9556 return ret;
9557}
9558
9559/**
9560 * wlan_hdd_disconnect() - hdd disconnect api
9561 * @pAdapter: Pointer to adapter
9562 * @reason: Disconnect reason code
9563 *
9564 * This function is used to issue a disconnect request to SME
9565 *
9566 * Return: 0 for success, non-zero for failure
9567 */
9568int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
9569{
9570 int status, result = 0;
9571 unsigned long rc;
9572 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9573 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9574
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309575 ENTER();
9576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009577 status = wlan_hdd_validate_context(pHddCtx);
9578
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309579 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581
9582 /*stop tx queues */
9583 hddLog(LOG1, FL("Disabling queues"));
9584 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
9585 WLAN_CONTROL_PATH);
9586 hddLog(LOG1,
9587 FL("Set HDD connState to eConnectionState_Disconnecting"));
9588 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
9589 INIT_COMPLETION(pAdapter->disconnect_comp_var);
9590
9591 /*issue disconnect */
9592
9593 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9594 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +05309595 /*
9596 * Wait here instead of returning directly, this will block the next
9597 * connect command and allow processing of the scan for ssid and
9598 * the previous connect command in CSR. Else we might hit some
9599 * race conditions leading to SME and HDD out of sync.
9600 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309601 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309602 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603 } else if (0 != status) {
9604 hddLog(LOGE,
9605 FL("csr_roam_disconnect failure, returned %d"),
9606 (int)status);
9607 pHddStaCtx->staDebugState = status;
9608 result = -EINVAL;
9609 goto disconnected;
9610 }
9611 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
9612 msecs_to_jiffies
9613 (WLAN_WAIT_TIME_DISCONNECT));
9614
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309615 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009616 hddLog(LOGE,
9617 FL("Failed to disconnect, timed out"));
9618 result = -ETIMEDOUT;
9619 }
9620disconnected:
9621 hddLog(LOG1,
9622 FL("Set HDD connState to eConnectionState_NotConnected"));
9623 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
9624#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
9625 /* Sending disconnect event to userspace for kernel version < 3.11
9626 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
9627 */
9628 hddLog(LOG1, FL("Send disconnected event to userspace"));
Ryan Hsua335c162016-01-21 12:12:20 -08009629 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, NULL, 0,
9630#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
9631 false,
9632#endif
9633 GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634#endif
9635
9636 return result;
9637}
9638
9639/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009640 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
9641 * @reason: ieee80211 reason code.
9642 *
9643 * This utility function helps log string conversion of reason code.
9644 *
9645 * Return: string conversion of reason code, if match found;
9646 * "Unknown" otherwise.
9647 */
9648static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
9649{
9650 switch (reason) {
9651 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
9652 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
9653 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
9654 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
9655 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
9656 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
9657 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
9658 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
9659 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
9660 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
9661 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
9662 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
9663 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
9664 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
9665 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
9666 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
9667 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
9668 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
9669 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
9670 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
9671 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
9672 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
9673 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
9674 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
9675 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
9676 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
9677 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
9678 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
9679 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
9680 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
9681 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
9682 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
9683 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
9684 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
9685 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
9686 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
9687 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
9688 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
9689 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
9690 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
9691 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
9692 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
9693 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
9694 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
9695 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
9696 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
9697 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
9698 default:
9699 return "Unknown";
9700 }
9701}
9702
9703/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009704 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9705 * @wiphy: Pointer to wiphy
9706 * @dev: Pointer to network device
9707 * @reason: Disconnect reason code
9708 *
9709 * This function is used to issue a disconnect request to SME
9710 *
9711 * Return: 0 for success, non-zero for failure
9712 */
9713static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9714 struct net_device *dev, u16 reason)
9715{
9716 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9717 int status;
9718 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9719 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9720#ifdef FEATURE_WLAN_TDLS
9721 uint8_t staIdx;
9722#endif
9723
9724 ENTER();
9725
Anurag Chouhan6d760662016-02-20 16:05:43 +05309726 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009727 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9728 return -EINVAL;
9729 }
9730
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309731 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732 TRACE_CODE_HDD_CFG80211_DISCONNECT,
9733 pAdapter->sessionId, reason));
9734 hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"),
9735 hdd_device_mode_to_string(pAdapter->device_mode),
9736 pAdapter->device_mode, reason);
9737
9738 status = wlan_hdd_validate_context(pHddCtx);
9739
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309740 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009741 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009742
9743 /* Issue disconnect request to SME, if station is in connected state */
9744 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
9745 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
9746 eCsrRoamDisconnectReason reasonCode =
9747 eCSR_DISCONNECT_REASON_UNSPECIFIED;
9748 hdd_scaninfo_t *pScanInfo;
9749
9750 switch (reason) {
9751 case WLAN_REASON_MIC_FAILURE:
9752 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
9753 break;
9754
9755 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
9756 case WLAN_REASON_DISASSOC_AP_BUSY:
9757 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
9758 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
9759 break;
9760
9761 case WLAN_REASON_PREV_AUTH_NOT_VALID:
9762 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
9763 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
9764 break;
9765
9766 case WLAN_REASON_DEAUTH_LEAVING:
9767 reasonCode =
9768 pHddCtx->config->
9769 gEnableDeauthToDisassocMap ?
9770 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
9771 eCSR_DISCONNECT_REASON_DEAUTH;
9772 break;
9773 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
9774 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
9775 break;
9776 default:
9777 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
9778 break;
9779 }
9780 hddLog(LOG1,
9781 FL("convert to internal reason %d to reasonCode %d"),
9782 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 pScanInfo = &pAdapter->scan_info;
9784 if (pScanInfo->mScanPending) {
9785 hddLog(LOG1,
9786 FL("Disconnect is in progress, Aborting Scan"));
9787 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
9788 eCSR_SCAN_ABORT_DEFAULT);
9789 }
9790#ifdef FEATURE_WLAN_TDLS
9791 /* First clean up the tdls peers if any */
9792 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
9793 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
9794 pAdapter->sessionId)
9795 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
9796 uint8_t *mac;
9797 mac =
9798 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
9799 hddLog(LOG1,
9800 "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d "
9801 MAC_ADDRESS_STR, __func__,
9802 pHddCtx->tdlsConnInfo[staIdx].staId,
9803 pAdapter->sessionId,
9804 MAC_ADDR_ARRAY(mac));
9805 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
9806 (pAdapter),
9807 pAdapter->sessionId, mac);
9808 }
9809 }
9810#endif
9811 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"),
9812 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009813 hdd_info("Disconnect request from user space with reason: %s",
9814 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009815 status = wlan_hdd_disconnect(pAdapter, reasonCode);
9816 if (0 != status) {
9817 hddLog(LOGE,
9818 FL("failure, returned %d"), status);
9819 return -EINVAL;
9820 }
9821 } else {
9822 hddLog(LOGE,
9823 FL("unexpected cfg disconnect called while in state (%d)"),
9824 pHddStaCtx->conn_info.connState);
9825 }
9826
9827 return status;
9828}
9829
9830/**
9831 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9832 * @wiphy: Pointer to wiphy
9833 * @dev: Pointer to network device
9834 * @reason: Disconnect reason code
9835 *
9836 * Return: 0 for success, non-zero for failure
9837 */
9838static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9839 struct net_device *dev, u16 reason)
9840{
9841 int ret;
9842 cds_ssr_protect(__func__);
9843 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
9844 cds_ssr_unprotect(__func__);
9845
9846 return ret;
9847}
9848
9849/**
9850 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
9851 * @pAdapter: Pointer to adapter
9852 * @param: Pointer to IBSS parameters
9853 *
9854 * This function is used to initialize the security settings in IBSS mode
9855 *
9856 * Return: 0 for success, non-zero for failure
9857 */
9858static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
9859 struct cfg80211_ibss_params
9860 *params)
9861{
9862 int status = 0;
9863 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9864 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9865 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9866
9867 ENTER();
9868
9869 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309870 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009871 pHddStaCtx->ibss_enc_key_installed = 0;
9872
9873 if (params->ie_len && (NULL != params->ie)) {
9874 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9875 params->ie_len, WLAN_EID_RSN)) {
9876 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9877 encryptionType = eCSR_ENCRYPT_TYPE_AES;
9878 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
9879 tDot11fIEWPA dot11WPAIE;
9880 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9881 u8 *ie;
9882
9883 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
9884 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9885 params->ie_len,
9886 DOT11F_EID_WPA);
9887 if (NULL != ie) {
9888 pWextState->wpaVersion =
9889 IW_AUTH_WPA_VERSION_WPA;
9890 /* Unpack the WPA IE */
9891 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
9892 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
9893 &ie[2 + 4],
9894 ie[1] - 4, &dot11WPAIE);
9895 /*Extract the multicast cipher, the encType for unicast
9896 cipher for wpa-none is none */
9897 encryptionType =
9898 hdd_translate_wpa_to_csr_encryption_type
9899 (dot11WPAIE.multicast_cipher);
9900 }
9901 }
9902
9903 status =
9904 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
9905 params->ie_len);
9906
9907 if (0 > status) {
9908 hddLog(LOGE, FL("failed to parse WPA/RSN IE"));
9909 return status;
9910 }
9911 }
9912
9913 pWextState->roamProfile.AuthType.authType[0] =
9914 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
9915
9916 if (params->privacy) {
9917 /* Security enabled IBSS, At this time there is no information
9918 * available about the security paramters, so initialise the
9919 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
9920 * The correct security parameters will be updated later in
9921 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
9922 * set inorder enable privacy bit in beacons
9923 */
9924
9925 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9926 }
9927 hddLog(LOG2, FL("encryptionType=%d"), encryptionType);
9928 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
9929 pWextState->roamProfile.EncryptionType.numEntries = 1;
9930 pWextState->roamProfile.EncryptionType.encryptionType[0] =
9931 encryptionType;
9932 return status;
9933}
9934
9935/**
9936 * __wlan_hdd_cfg80211_join_ibss() - join ibss
9937 * @wiphy: Pointer to wiphy
9938 * @dev: Pointer to network device
9939 * @param: Pointer to IBSS join parameters
9940 *
9941 * This function is used to create/join an IBSS network
9942 *
9943 * Return: 0 for success, non-zero for failure
9944 */
9945static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9946 struct net_device *dev,
9947 struct cfg80211_ibss_params *params)
9948{
9949 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9950 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9951 tCsrRoamProfile *pRoamProfile;
9952 int status;
9953 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9954 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +05309955 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009956 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957
9958 ENTER();
9959
Anurag Chouhan6d760662016-02-20 16:05:43 +05309960 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9962 return -EINVAL;
9963 }
9964
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309965 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009966 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
9967 pAdapter->sessionId, pAdapter->device_mode));
9968 hddLog(LOG1, FL("Device_mode %s(%d)"),
9969 hdd_device_mode_to_string(pAdapter->device_mode),
9970 pAdapter->device_mode);
9971
9972 status = wlan_hdd_validate_context(pHddCtx);
9973
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309974 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009976
9977 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05309978 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9980 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9981 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9982 int indx;
9983
9984 /* Get channel number */
9985 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 params->
9987 chandef.
9988 chan->
9989 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990
9991 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9992 validChan, &numChans)) {
9993 hddLog(LOGE, FL("No valid channel list"));
9994 return -EOPNOTSUPP;
9995 }
9996
9997 for (indx = 0; indx < numChans; indx++) {
9998 if (channelNum == validChan[indx]) {
9999 break;
10000 }
10001 }
10002 if (indx >= numChans) {
10003 hddLog(LOGE,
10004 FL("Not valid Channel %d"), channelNum);
10005 return -EINVAL;
10006 }
10007 }
10008
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010009 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010010 HW_MODE_20_MHZ)) {
10011 hdd_err("This concurrency combination is not allowed");
10012 return -ECONNREFUSED;
10013 }
10014 if (pHddCtx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010015 status = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010016 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 hdd_err("ERR: clear event failed");
10018
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +053010019 status = cds_current_connections_update(pAdapter->sessionId,
10020 channelNum,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +053010021 SIR_UPDATE_REASON_JOIN_IBSS);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010022 if (QDF_STATUS_E_FAILURE == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010023 hdd_err("ERROR: connections update failed!!");
10024 return -EINVAL;
10025 }
10026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010027 if (QDF_STATUS_SUCCESS == status) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010028 status = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010029 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010030 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010031 return -EINVAL;
10032 }
10033 }
10034 }
10035
10036 /*Try disconnecting if already in connected state */
10037 status = wlan_hdd_try_disconnect(pAdapter);
10038 if (0 > status) {
10039 hddLog(LOGE,
10040 FL("Failed to disconnect the existing IBSS connection"));
10041 return -EALREADY;
10042 }
10043
10044 pRoamProfile = &pWextState->roamProfile;
10045
10046 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
10047 hddLog(LOGE,
10048 FL("Interface type is not set to IBSS"));
10049 return -EINVAL;
10050 }
10051
10052 /* enable selected protection checks in IBSS mode */
10053 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
10054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010055 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 WNI_CFG_IBSS_ATIM_WIN_SIZE,
10057 pHddCtx->config->
10058 ibssATIMWinSize)) {
10059 hddLog(LOGE,
10060 FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"));
10061 }
10062
10063 /* BSSID is provided by upper layers hence no need to AUTO generate */
10064 if (NULL != params->bssid) {
10065 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010066 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 hddLog(LOGE,
10068 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
10069 return -EIO;
10070 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010071 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010072 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
10073 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010074 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010075 hddLog(LOGE,
10076 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
10077 return -EIO;
10078 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053010079 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010080 }
10081 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
10082 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
10083 pRoamProfile->beaconInterval = params->beacon_interval;
10084 else {
10085 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
10086 hddLog(LOG2,
10087 FL("input beacon interval %d TU is invalid, use default %d TU"),
10088 params->beacon_interval, pRoamProfile->beaconInterval);
10089 }
10090
10091 /* Set Channel */
10092 if (channelNum) {
10093 /* Set the Operational Channel */
10094 hddLog(LOG2, FL("set channel %d"), channelNum);
10095 pRoamProfile->ChannelInfo.numOfChannels = 1;
10096 pHddStaCtx->conn_info.operationChannel = channelNum;
10097 pRoamProfile->ChannelInfo.ChannelList =
10098 &pHddStaCtx->conn_info.operationChannel;
10099 }
10100
10101 /* Initialize security parameters */
10102 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
10103 if (status < 0) {
10104 hddLog(LOGE,
10105 FL("failed to set security parameters"));
10106 return status;
10107 }
10108
10109 /* Issue connect start */
10110 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
10111 params->ssid_len,
10112 bssid.bytes,
10113 NULL,
10114 pHddStaCtx->conn_info.
10115 operationChannel);
10116
10117 if (0 > status) {
10118 hddLog(LOGE, FL("connect failed"));
10119 return status;
10120 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010121 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122 return 0;
10123}
10124
10125/**
10126 * wlan_hdd_cfg80211_join_ibss() - join ibss
10127 * @wiphy: Pointer to wiphy
10128 * @dev: Pointer to network device
10129 * @param: Pointer to IBSS join parameters
10130 *
10131 * This function is used to create/join an IBSS network
10132 *
10133 * Return: 0 for success, non-zero for failure
10134 */
10135static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
10136 struct net_device *dev,
10137 struct cfg80211_ibss_params *params)
10138{
10139 int ret = 0;
10140
10141 cds_ssr_protect(__func__);
10142 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
10143 cds_ssr_unprotect(__func__);
10144
10145 return ret;
10146}
10147
10148/**
10149 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
10150 * @wiphy: Pointer to wiphy
10151 * @dev: Pointer to network device
10152 *
10153 * This function is used to leave an IBSS network
10154 *
10155 * Return: 0 for success, non-zero for failure
10156 */
10157static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
10158 struct net_device *dev)
10159{
10160 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10161 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10162 tCsrRoamProfile *pRoamProfile;
10163 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10164 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010165 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053010166 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080010167 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168
10169 ENTER();
10170
Anurag Chouhan6d760662016-02-20 16:05:43 +053010171 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010172 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10173 return -EINVAL;
10174 }
10175
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010176 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010177 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
10178 pAdapter->sessionId,
10179 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
10180 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010181 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010182 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183
10184 hddLog(LOG1, FL("Device_mode %s(%d)"),
10185 hdd_device_mode_to_string(pAdapter->device_mode),
10186 pAdapter->device_mode);
10187 if (NULL == pWextState) {
10188 hddLog(LOGE, FL("Data Storage Corruption"));
10189 return -EIO;
10190 }
10191
10192 pRoamProfile = &pWextState->roamProfile;
10193
10194 /* Issue disconnect only if interface type is set to IBSS */
10195 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
10196 hddLog(LOGE,
10197 FL("BSS Type is not set to IBSS"));
10198 return -EINVAL;
10199 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080010200 /* Clearing add IE of beacon */
10201 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
10202 sizeof(tSirMacAddr));
10203 updateIE.smeSessionId = pAdapter->sessionId;
10204 updateIE.ieBufferlength = 0;
10205 updateIE.pAdditionIEBuffer = NULL;
10206 updateIE.append = true;
10207 updateIE.notify = true;
10208 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
10209 &updateIE,
10210 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
10211 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
10212 }
10213
10214 /* Reset WNI_CFG_PROBE_RSP Flags */
10215 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216
10217 /* Issue Disconnect request */
10218 INIT_COMPLETION(pAdapter->disconnect_comp_var);
10219 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
10220 pAdapter->sessionId,
10221 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010222 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223 hddLog(LOGE,
10224 FL("sme_roam_disconnect failed hal_status(%d)"),
10225 hal_status);
10226 return -EAGAIN;
10227 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053010228
10229 /* wait for mc thread to cleanup and then return to upper stack
10230 * so by the time upper layer calls the change interface, we are
10231 * all set to proceed further
10232 */
10233 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
10234 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
10235 if (!rc) {
10236 hdd_err("Failed to disconnect, timed out");
10237 return -ETIMEDOUT;
10238 }
10239
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010240 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241 return 0;
10242}
10243
10244/**
10245 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
10246 * @wiphy: Pointer to wiphy
10247 * @dev: Pointer to network device
10248 *
10249 * This function is used to leave an IBSS network
10250 *
10251 * Return: 0 for success, non-zero for failure
10252 */
10253static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
10254 struct net_device *dev)
10255{
10256 int ret = 0;
10257
10258 cds_ssr_protect(__func__);
10259 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
10260 cds_ssr_unprotect(__func__);
10261
10262 return ret;
10263}
10264
10265/**
10266 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
10267 * @wiphy: Pointer to wiphy
10268 * @changed: Parameters changed
10269 *
10270 * This function is used to set the phy parameters. RTS Threshold/FRAG
10271 * Threshold/Retry Count etc.
10272 *
10273 * Return: 0 for success, non-zero for failure
10274 */
10275static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
10276 u32 changed)
10277{
10278 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10279 tHalHandle hHal = pHddCtx->hHal;
10280 int status;
10281
10282 ENTER();
10283
Anurag Chouhan6d760662016-02-20 16:05:43 +053010284 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10286 return -EINVAL;
10287 }
10288
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010289 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
10291 NO_SESSION, wiphy->rts_threshold));
10292 status = wlan_hdd_validate_context(pHddCtx);
10293
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010294 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010295 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296
10297 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
10298 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
10299 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
10300
10301 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
10302 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
10303 hddLog(LOGE,
10304 FL("Invalid RTS Threshold value %u"),
10305 rts_threshold);
10306 return -EINVAL;
10307 }
10308
10309 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
10310 rts_threshold)) {
10311 hddLog(LOGE,
10312 FL("sme_cfg_set_int failed for rts_threshold value %u"),
10313 rts_threshold);
10314 return -EIO;
10315 }
10316
10317 hddLog(LOG2, FL("set rts threshold %u"), rts_threshold);
10318 }
10319
10320 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
10321 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
10322 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
10323 wiphy->frag_threshold;
10324
10325 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
10326 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
10327 hddLog(LOGE,
10328 FL("Invalid frag_threshold value %hu"),
10329 frag_threshold);
10330 return -EINVAL;
10331 }
10332
10333 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
10334 frag_threshold)) {
10335 hddLog(LOGE,
10336 FL("sme_cfg_set_int failed for frag_threshold value %hu"),
10337 frag_threshold);
10338 return -EIO;
10339 }
10340
10341 hddLog(LOG2, FL("set frag threshold %hu"), frag_threshold);
10342 }
10343
10344 if ((changed & WIPHY_PARAM_RETRY_SHORT)
10345 || (changed & WIPHY_PARAM_RETRY_LONG)) {
10346 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
10347 wiphy->retry_short : wiphy->retry_long;
10348
10349 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
10350 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
10351 hddLog(LOGE,
10352 FL("Invalid Retry count %hu"), retry_value);
10353 return -EINVAL;
10354 }
10355
10356 if (changed & WIPHY_PARAM_RETRY_SHORT) {
10357 if (0 != sme_cfg_set_int(hHal,
10358 WNI_CFG_LONG_RETRY_LIMIT,
10359 retry_value)) {
10360 hddLog(LOGE,
10361 FL("sme_cfg_set_int failed for long retry count %hu"),
10362 retry_value);
10363 return -EIO;
10364 }
10365 hddLog(LOG2,
10366 FL("set long retry count %hu"), retry_value);
10367 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
10368 if (0 != sme_cfg_set_int(hHal,
10369 WNI_CFG_SHORT_RETRY_LIMIT,
10370 retry_value)) {
10371 hddLog(LOGE,
10372 FL("sme_cfg_set_int failed for short retry count %hu"),
10373 retry_value);
10374 return -EIO;
10375 }
10376 hddLog(LOG2,
10377 FL("set short retry count %hu"), retry_value);
10378 }
10379 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010380 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010381 return 0;
10382}
10383
10384/**
10385 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
10386 * @wiphy: Pointer to wiphy
10387 * @changed: Parameters changed
10388 *
10389 * Return: 0 for success, non-zero for failure
10390 */
10391static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
10392{
10393 int ret;
10394
10395 cds_ssr_protect(__func__);
10396 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
10397 cds_ssr_unprotect(__func__);
10398
10399 return ret;
10400}
10401
10402/**
10403 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
10404 * key
10405 * @wiphy: Pointer to wiphy
10406 * @dev: Pointer to network device
10407 * @key_index: Key index
10408 *
10409 * Return: 0
10410 */
10411static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
10412 struct net_device *netdev,
10413 u8 key_index)
10414{
10415 ENTER();
10416 return 0;
10417}
10418
10419/**
10420 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
10421 * wlan_hdd_set_default_mgmt_key
10422 * @wiphy: pointer to wiphy
10423 * @netdev: pointer to net_device structure
10424 * @key_index: key index
10425 *
10426 * Return: 0 on success, error number on failure
10427 */
10428static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
10429 struct net_device *netdev,
10430 u8 key_index)
10431{
10432 int ret;
10433
10434 cds_ssr_protect(__func__);
10435 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
10436 cds_ssr_unprotect(__func__);
10437
10438 return ret;
10439}
10440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010441/**
10442 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
10443 * @wiphy: Pointer to wiphy
10444 * @dev: Pointer to network device
10445 * @params: Pointer to tx queue parameters
10446 *
10447 * Return: 0
10448 */
10449static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
10450 struct net_device *dev,
10451 struct ieee80211_txq_params *params)
10452{
10453 ENTER();
10454 return 0;
10455}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010456
10457/**
10458 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
10459 * @wiphy: pointer to wiphy
10460 * @netdev: pointer to net_device structure
10461 * @params: pointer to ieee80211_txq_params
10462 *
10463 * Return: 0 on success, error number on failure
10464 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010465static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
10466 struct net_device *dev,
10467 struct ieee80211_txq_params *params)
10468{
10469 int ret;
10470
10471 cds_ssr_protect(__func__);
10472 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
10473 cds_ssr_unprotect(__func__);
10474
10475 return ret;
10476}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010477
10478/**
10479 * __wlan_hdd_cfg80211_del_station() - delete station v2
10480 * @wiphy: Pointer to wiphy
10481 * @param: Pointer to delete station parameter
10482 *
10483 * Return: 0 for success, non-zero for failure
10484 */
10485static
10486int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10487 struct net_device *dev,
10488 struct tagCsrDelStaParams *pDelStaParams)
10489{
10490 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10491 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010492 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010493 hdd_hostapd_state_t *hapd_state;
10494 int status;
10495 uint8_t staId;
10496 uint8_t *mac;
10497
10498 ENTER();
10499
Anurag Chouhan6d760662016-02-20 16:05:43 +053010500 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010501 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10502 return -EINVAL;
10503 }
10504
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010505 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 TRACE_CODE_HDD_CFG80211_DEL_STA,
10507 pAdapter->sessionId, pAdapter->device_mode));
10508
10509 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10510 status = wlan_hdd_validate_context(pHddCtx);
10511
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010512 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010513 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010514
10515 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
10516
Krunal Sonib4326f22016-03-10 13:05:51 -080010517 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
10518 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010519
10520 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10521 if (!hapd_state) {
10522 hddLog(LOGE, "%s: Hostapd State is Null", __func__);
10523 return 0;
10524 }
10525
Anurag Chouhanc5548422016-02-24 18:33:27 +053010526 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010527 uint16_t i;
10528 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
10529 if ((pAdapter->aStaInfo[i].isUsed) &&
10530 (!pAdapter->aStaInfo[i].
10531 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010532 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010533 mac,
10534 pAdapter->aStaInfo[i].
10535 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010536 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010537 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
10538 hdd_ipa_wlan_evt(pAdapter,
10539 pAdapter->
10540 aStaInfo[i].
10541 ucSTAId,
10542 WLAN_CLIENT_DISCONNECT,
10543 mac);
10544 }
10545 hddLog(LOG1,
10546 FL("Delete STA with MAC::"
10547 MAC_ADDRESS_STR),
10548 MAC_ADDR_ARRAY(mac));
10549
10550 if (pHddCtx->dev_dfs_cac_status ==
10551 DFS_CAC_IN_PROGRESS)
10552 goto fn_end;
10553
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010554 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010555 hdd_softap_sta_disassoc(pAdapter,
10556 mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010557 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010558 hdd_softap_sta_deauth(pAdapter,
10559 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010560 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561 pAdapter->aStaInfo[i].
10562 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010563 qdf_status =
10564 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010565 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010566 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010567 if (!QDF_IS_STATUS_SUCCESS(
10568 qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569 hddLog(LOGE,
10570 "%s: Deauth wait time expired",
10571 __func__);
10572 }
10573 }
10574 }
10575 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010576 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010577 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010578 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010579 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010580 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010581 hddLog(LOG1,
10582 FL("Skip DEL STA as this is not used::"
10583 MAC_ADDRESS_STR),
10584 MAC_ADDR_ARRAY(mac));
10585 return -ENOENT;
10586 }
10587
10588 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
10589 hdd_ipa_wlan_evt(pAdapter, staId,
10590 WLAN_CLIENT_DISCONNECT, mac);
10591 }
10592
10593 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
10594 true) {
10595 hddLog(LOG1,
10596 FL("Skip DEL STA as deauth is in progress::"
10597 MAC_ADDRESS_STR),
10598 MAC_ADDR_ARRAY(mac));
10599 return -ENOENT;
10600 }
10601
10602 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
10603
10604 hddLog(LOG1,
10605 FL("Delete STA with MAC::" MAC_ADDRESS_STR),
10606 MAC_ADDR_ARRAY(mac));
10607
10608 /* Case: SAP in ACS selected DFS ch and client connected
10609 * Now Radar detected. Then if random channel is another
10610 * DFS ch then new CAC is initiated and no TX allowed.
10611 * So do not send any mgmt frames as it will timeout
10612 * during CAC.
10613 */
10614
10615 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
10616 goto fn_end;
10617
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010618 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010619 hdd_softap_sta_disassoc(pAdapter, mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010620 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010621 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010622 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010623 pAdapter->aStaInfo[staId].isDeauthInProgress =
10624 false;
10625 hddLog(LOG1,
10626 FL("STA removal failed for ::"
10627 MAC_ADDRESS_STR),
10628 MAC_ADDR_ARRAY(mac));
10629 return -ENOENT;
10630 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010631 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010632 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010634 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 hddLog(LOGE,
10636 "%s: Deauth wait time expired",
10637 __func__);
10638 }
10639 }
10640 }
10641
10642fn_end:
10643 EXIT();
10644 return 0;
10645}
10646
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010647#if defined(USE_CFG80211_DEL_STA_V2)
10648/**
10649 * wlan_hdd_del_station() - delete station wrapper
10650 * @adapter: pointer to the hdd adapter
10651 *
10652 * Return: None
10653 */
10654void wlan_hdd_del_station(hdd_adapter_t *adapter)
10655{
10656 struct station_del_parameters del_sta;
10657 del_sta.mac = NULL;
10658 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10659 del_sta.reason_code = eCsrForcedDeauthSta;
10660
10661 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
10662 &del_sta);
10663}
10664#else
10665void wlan_hdd_del_station(hdd_adapter_t *adapter)
10666{
10667 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
10668}
10669#endif
10670
10671#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010672/**
10673 * wlan_hdd_cfg80211_del_station() - delete station v2
10674 * @wiphy: Pointer to wiphy
10675 * @param: Pointer to delete station parameter
10676 *
10677 * Return: 0 for success, non-zero for failure
10678 */
10679int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10680 struct net_device *dev,
10681 struct station_del_parameters *param)
10682#else
10683/**
10684 * wlan_hdd_cfg80211_del_station() - delete station
10685 * @wiphy: Pointer to wiphy
10686 * @mac: Pointer to station mac address
10687 *
10688 * Return: 0 for success, non-zero for failure
10689 */
10690#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10691int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10692 struct net_device *dev,
10693 const uint8_t *mac)
10694#else
10695int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10696 struct net_device *dev,
10697 uint8_t *mac)
10698#endif
10699#endif
10700{
10701 int ret;
10702 struct tagCsrDelStaParams delStaParams;
10703
10704 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010705#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010707 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708 return -EINVAL;
10709 }
10710 wlansap_populate_del_sta_params(param->mac, param->reason_code,
10711 param->subtype, &delStaParams);
10712#else
10713 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
10714 (SIR_MAC_MGMT_DEAUTH >> 4),
10715 &delStaParams);
10716#endif
10717 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
10718 cds_ssr_unprotect(__func__);
10719
10720 return ret;
10721}
10722
10723/**
10724 * __wlan_hdd_cfg80211_add_station() - add station
10725 * @wiphy: Pointer to wiphy
10726 * @mac: Pointer to station mac address
10727 * @pmksa: Pointer to add station parameter
10728 *
10729 * Return: 0 for success, non-zero for failure
10730 */
10731static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10732 struct net_device *dev,
10733 const uint8_t *mac,
10734 struct station_parameters *params)
10735{
10736 int status = -EPERM;
10737#ifdef FEATURE_WLAN_TDLS
10738 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10739 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10740 u32 mask, set;
10741
10742 ENTER();
10743
Anurag Chouhan6d760662016-02-20 16:05:43 +053010744 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010745 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10746 return -EINVAL;
10747 }
10748
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010749 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750 TRACE_CODE_HDD_CFG80211_ADD_STA,
10751 pAdapter->sessionId, params->listen_interval));
10752
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010753 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010754 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755
10756 mask = params->sta_flags_mask;
10757
10758 set = params->sta_flags_set;
10759
10760 hddLog(LOG1, FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), mask, set,
10761 MAC_ADDR_ARRAY(mac));
10762
10763 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10764 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10765 status =
10766 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
10767 }
10768 }
10769#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010770 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771 return status;
10772}
10773
10774/**
10775 * wlan_hdd_cfg80211_add_station() - add station
10776 * @wiphy: Pointer to wiphy
10777 * @mac: Pointer to station mac address
10778 * @pmksa: Pointer to add station parameter
10779 *
10780 * Return: 0 for success, non-zero for failure
10781 */
10782#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10783static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10784 struct net_device *dev,
10785 const uint8_t *mac,
10786 struct station_parameters *params)
10787#else
10788static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10789 struct net_device *dev, uint8_t *mac,
10790 struct station_parameters *params)
10791#endif
10792{
10793 int ret;
10794
10795 cds_ssr_protect(__func__);
10796 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
10797 cds_ssr_unprotect(__func__);
10798
10799 return ret;
10800}
10801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802/**
10803 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
10804 * @wiphy: Pointer to wiphy
10805 * @dev: Pointer to network device
10806 * @pmksa: Pointer to set pmksa parameter
10807 *
10808 * Return: 0 for success, non-zero for failure
10809 */
10810static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10811 struct net_device *dev,
10812 struct cfg80211_pmksa *pmksa)
10813{
10814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10815 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10816 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010817 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818 int status;
10819 tPmkidCacheInfo pmk_id;
10820
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010821 ENTER();
10822
Anurag Chouhan6d760662016-02-20 16:05:43 +053010823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10825 return -EINVAL;
10826 }
10827
10828 if (!pmksa) {
10829 hddLog(LOGE, FL("pmksa is NULL"));
10830 return -EINVAL;
10831 }
10832
10833 if (!pmksa->bssid || !pmksa->pmkid) {
10834 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
10835 pmksa->bssid, pmksa->pmkid);
10836 return -EINVAL;
10837 }
10838
10839 hddLog(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR),
10840 MAC_ADDR_ARRAY(pmksa->bssid));
10841
10842 status = wlan_hdd_validate_context(pHddCtx);
10843
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010844 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846
10847 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10848
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010849 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
10850 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851
10852 /* Add to the PMKSA ID Cache in CSR */
10853 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
10854 &pmk_id, 1, false);
10855
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010856 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
10858 pAdapter->sessionId, result));
10859
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010860 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010861 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862}
10863
10864/**
10865 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
10866 * @wiphy: Pointer to wiphy
10867 * @dev: Pointer to network device
10868 * @pmksa: Pointer to set pmksa parameter
10869 *
10870 * Return: 0 for success, non-zero for failure
10871 */
10872static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10873 struct net_device *dev,
10874 struct cfg80211_pmksa *pmksa)
10875{
10876 int ret;
10877
10878 cds_ssr_protect(__func__);
10879 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
10880 cds_ssr_unprotect(__func__);
10881
10882 return ret;
10883}
10884
10885/**
10886 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10887 * @wiphy: Pointer to wiphy
10888 * @dev: Pointer to network device
10889 * @pmksa: Pointer to pmksa parameter
10890 *
10891 * Return: 0 for success, non-zero for failure
10892 */
10893static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10894 struct net_device *dev,
10895 struct cfg80211_pmksa *pmksa)
10896{
10897 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10898 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10899 tHalHandle halHandle;
10900 int status = 0;
10901
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010902 ENTER();
10903
Anurag Chouhan6d760662016-02-20 16:05:43 +053010904 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010905 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10906 return -EINVAL;
10907 }
10908
10909 if (!pmksa) {
10910 hddLog(LOGE, FL("pmksa is NULL"));
10911 return -EINVAL;
10912 }
10913
10914 if (!pmksa->bssid) {
10915 hddLog(LOGE, FL("pmksa->bssid is NULL"));
10916 return -EINVAL;
10917 }
10918
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010919 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 MAC_ADDR_ARRAY(pmksa->bssid));
10921
10922 status = wlan_hdd_validate_context(pHddCtx);
10923
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010924 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010925 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926
10927 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10928
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010929 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010930 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
10931 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010933 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010934 sme_roam_del_pmkid_from_cache(halHandle,
10935 pAdapter->sessionId, pmksa->bssid,
10936 false)) {
10937 hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR),
10938 MAC_ADDR_ARRAY(pmksa->bssid));
10939 status = -EINVAL;
10940 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010941 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 return status;
10943}
10944
10945/**
10946 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10947 * @wiphy: Pointer to wiphy
10948 * @dev: Pointer to network device
10949 * @pmksa: Pointer to pmksa parameter
10950 *
10951 * Return: 0 for success, non-zero for failure
10952 */
10953static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10954 struct net_device *dev,
10955 struct cfg80211_pmksa *pmksa)
10956{
10957 int ret;
10958
10959 cds_ssr_protect(__func__);
10960 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
10961 cds_ssr_unprotect(__func__);
10962
10963 return ret;
10964
10965}
10966
10967/**
10968 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10969 * @wiphy: Pointer to wiphy
10970 * @dev: Pointer to network device
10971 *
10972 * Return: 0 for success, non-zero for failure
10973 */
10974static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10975 struct net_device *dev)
10976{
10977 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10978 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10979 tHalHandle halHandle;
10980 int status = 0;
10981
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010982 ENTER();
10983
Anurag Chouhan6d760662016-02-20 16:05:43 +053010984 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010985 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10986 return -EINVAL;
10987 }
10988
10989 hddLog(LOGW, FL("Flushing PMKSA"));
10990
10991 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10992 status = wlan_hdd_validate_context(pHddCtx);
10993
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010994 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010995 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996
10997 /* Retrieve halHandle */
10998 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10999
11000 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011001 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
11003 true)) {
11004 hddLog(LOGE, FL("Cannot flush PMKIDCache"));
11005 status = -EINVAL;
11006 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011007 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 return status;
11009}
11010
11011/**
11012 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
11013 * @wiphy: Pointer to wiphy
11014 * @dev: Pointer to network device
11015 *
11016 * Return: 0 for success, non-zero for failure
11017 */
11018static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
11019 struct net_device *dev)
11020{
11021 int ret;
11022
11023 cds_ssr_protect(__func__);
11024 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
11025 cds_ssr_unprotect(__func__);
11026
11027 return ret;
11028}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011029
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080011030#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011031/**
11032 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
11033 * @wiphy: Pointer to wiphy
11034 * @dev: Pointer to network device
11035 * @ftie: Pointer to fast transition ie parameter
11036 *
11037 * Return: 0 for success, non-zero for failure
11038 */
11039static int
11040__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
11041 struct net_device *dev,
11042 struct cfg80211_update_ft_ies_params *ftie)
11043{
11044 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
11045 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11046 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11047 int status;
11048
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011049 ENTER();
11050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011051 status = wlan_hdd_validate_context(hdd_ctx);
11052 if (status)
11053 return status;
11054
Anurag Chouhan6d760662016-02-20 16:05:43 +053011055 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11057 return -EINVAL;
11058 }
11059
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011060 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011061 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
11062 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
11063 /* Added for debug on reception of Re-assoc Req. */
11064 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
11065 hddLog(LOGE,
11066 FL("Called with Ie of length = %zu when not associated"),
11067 ftie->ie_len);
11068 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
11069 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__,
11071 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011072
11073 /* Pass the received FT IEs to SME */
11074 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
11075 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011076 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011077 return 0;
11078}
11079
11080/**
11081 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
11082 * @wiphy: Pointer to wiphy
11083 * @dev: Pointer to network device
11084 * @ftie: Pointer to fast transition ie parameter
11085 *
11086 * Return: 0 for success, non-zero for failure
11087 */
11088static int
11089wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
11090 struct net_device *dev,
11091 struct cfg80211_update_ft_ies_params *ftie)
11092{
11093 int ret;
11094
11095 cds_ssr_protect(__func__);
11096 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
11097 cds_ssr_unprotect(__func__);
11098
11099 return ret;
11100}
11101#endif
11102
11103#ifdef WLAN_FEATURE_GTK_OFFLOAD
11104/**
11105 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
11106 * @callbackContext: Callback context
11107 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
11108 *
11109 * Callback rountine called upon receiving response for get offload info
11110 *
11111 * Return: none
11112 */
11113void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
11114 tpSirGtkOffloadGetInfoRspParams
11115 pGtkOffloadGetInfoRsp)
11116{
11117 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
11118 uint8_t tempReplayCounter[8];
11119 hdd_station_ctx_t *pHddStaCtx;
11120
11121 ENTER();
11122
11123 if (NULL == pAdapter) {
11124 hddLog(LOGE, FL("HDD adapter is Null"));
11125 return;
11126 }
11127
11128 if (NULL == pGtkOffloadGetInfoRsp) {
11129 hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null"));
11130 return;
11131 }
11132
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011133 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011134 hddLog(LOGE, FL("wlan Failed to get replay counter value"));
11135 return;
11136 }
11137
11138 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11139 /* Update replay counter */
11140 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
11141 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
11142
11143 {
11144 /* changing from little to big endian since supplicant
11145 * works on big endian format
11146 */
11147 int i;
11148 uint8_t *p =
11149 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
11150
11151 for (i = 0; i < 8; i++) {
11152 tempReplayCounter[7 - i] = (uint8_t) p[i];
11153 }
11154 }
11155
11156 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080011157 cfg80211_gtk_rekey_notify(pAdapter->dev,
11158 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159 tempReplayCounter, GFP_KERNEL);
11160}
11161
11162/**
11163 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
11164 * @wiphy: Pointer to wiphy
11165 * @dev: Pointer to network device
11166 * @data: Pointer to rekey data
11167 *
11168 * This function is used to offload GTK rekeying job to the firmware.
11169 *
11170 * Return: 0 for success, non-zero for failure
11171 */
11172int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
11173 struct net_device *dev,
11174 struct cfg80211_gtk_rekey_data *data)
11175{
11176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11177 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11178 hdd_station_ctx_t *pHddStaCtx;
11179 tHalHandle hHal;
11180 int result;
11181 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011182 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183
11184 ENTER();
11185
Anurag Chouhan6d760662016-02-20 16:05:43 +053011186 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11188 return -EINVAL;
11189 }
11190
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011191 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
11193 pAdapter->sessionId, pAdapter->device_mode));
11194
11195 result = wlan_hdd_validate_context(pHddCtx);
11196
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011197 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011198 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199
11200 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11201 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11202 if (NULL == hHal) {
11203 hddLog(LOGE, FL("HAL context is Null!!!"));
11204 return -EAGAIN;
11205 }
11206
11207 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
11208 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
11209 NL80211_KCK_LEN);
11210 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
11211 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053011212 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080011213 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011214 {
11215 /* changing from big to little endian since driver
11216 * works on little endian format
11217 */
11218 uint8_t *p =
11219 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
11220 ullKeyReplayCounter;
11221 int i;
11222
11223 for (i = 0; i < 8; i++) {
11224 p[7 - i] = data->replay_ctr[i];
11225 }
11226 }
11227
11228 if (true == pHddCtx->hdd_wlan_suspended) {
11229 /* if wlan is suspended, enable GTK offload directly from here */
11230 memcpy(&hddGtkOffloadReqParams,
11231 &pHddStaCtx->gtkOffloadReqParams,
11232 sizeof(tSirGtkOffloadParams));
11233 status =
11234 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
11235 pAdapter->sessionId);
11236
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011237 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"),
11239 status);
11240 return -EINVAL;
11241 }
11242 hddLog(LOG1, FL("sme_set_gtk_offload successful"));
11243 } else {
11244 hddLog(LOG1,
11245 FL("wlan not suspended GTKOffload request is stored"));
11246 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011247 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011248 return result;
11249}
11250
11251/**
11252 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
11253 * @wiphy: Pointer to wiphy
11254 * @dev: Pointer to network device
11255 * @data: Pointer to rekey data
11256 *
11257 * This function is used to offload GTK rekeying job to the firmware.
11258 *
11259 * Return: 0 for success, non-zero for failure
11260 */
11261int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
11262 struct net_device *dev,
11263 struct cfg80211_gtk_rekey_data *data)
11264{
11265 int ret;
11266
11267 cds_ssr_protect(__func__);
11268 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
11269 cds_ssr_unprotect(__func__);
11270
11271 return ret;
11272}
11273#endif /*WLAN_FEATURE_GTK_OFFLOAD */
11274
11275/**
11276 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
11277 * @wiphy: Pointer to wiphy
11278 * @dev: Pointer to network device
11279 * @param: Pointer to access control parameter
11280 *
11281 * Return: 0 for success, non-zero for failure
11282 */
11283static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
11284 struct net_device *dev,
11285 const struct cfg80211_acl_data *params)
11286{
11287 int i;
11288 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11289 hdd_hostapd_state_t *pHostapdState;
11290 tsap_Config_t *pConfig;
11291 v_CONTEXT_t p_cds_context = NULL;
11292 hdd_context_t *pHddCtx;
11293 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011294 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011295
11296 ENTER();
11297
Anurag Chouhan6d760662016-02-20 16:05:43 +053011298 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011299 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11300 return -EINVAL;
11301 }
11302
11303 if (NULL == params) {
11304 hddLog(LOGE, FL("params is Null"));
11305 return -EINVAL;
11306 }
11307
11308 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11309 status = wlan_hdd_validate_context(pHddCtx);
11310
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011311 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011313
11314 p_cds_context = pHddCtx->pcds_context;
11315 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11316
11317 if (NULL == pHostapdState) {
11318 hddLog(LOGE, FL("pHostapdState is Null"));
11319 return -EINVAL;
11320 }
11321
11322 hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy,
11323 params->n_acl_entries);
11324
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011325 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053011326 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
11327 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080011328 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
11330
11331 /* default value */
11332 pConfig->num_accept_mac = 0;
11333 pConfig->num_deny_mac = 0;
11334
11335 /**
11336 * access control policy
11337 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
11338 * listed in hostapd.deny file.
11339 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
11340 * listed in hostapd.accept file.
11341 */
11342 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
11343 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
11344 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
11345 params->acl_policy) {
11346 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
11347 } else {
11348 hddLog(LOGE, FL("Acl Policy : %d is not supported"),
11349 params->acl_policy);
11350 return -ENOTSUPP;
11351 }
11352
11353 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
11354 pConfig->num_accept_mac = params->n_acl_entries;
11355 for (i = 0; i < params->n_acl_entries; i++) {
11356 hddLog(LOG1,
11357 FL("** Add ACL MAC entry %i in WhiletList :"
11358 MAC_ADDRESS_STR), i,
11359 MAC_ADDR_ARRAY(
11360 params->mac_addrs[i].addr));
11361
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011362 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011363 params->mac_addrs[i].addr,
11364 sizeof(qcmacaddr));
11365 }
11366 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
11367 pConfig->num_deny_mac = params->n_acl_entries;
11368 for (i = 0; i < params->n_acl_entries; i++) {
11369 hddLog(LOG1,
11370 FL("** Add ACL MAC entry %i in BlackList :"
11371 MAC_ADDRESS_STR), i,
11372 MAC_ADDR_ARRAY(
11373 params->mac_addrs[i].addr));
11374
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011375 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376 params->mac_addrs[i].addr,
11377 sizeof(qcmacaddr));
11378 }
11379 }
11380#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011381 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
11383 pConfig);
11384#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011385 qdf_status = wlansap_set_mac_acl(p_cds_context, pConfig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011386#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011387 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011388 hddLog(LOGE, FL("SAP Set Mac Acl fail"));
11389 return -EINVAL;
11390 }
11391 } else {
11392 hddLog(LOG1, FL("Invalid device_mode %s(%d)"),
11393 hdd_device_mode_to_string(pAdapter->device_mode),
11394 pAdapter->device_mode);
11395 return -EINVAL;
11396 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011397 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011398 return 0;
11399}
11400
11401/**
11402 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
11403 * __wlan_hdd_cfg80211_set_mac_acl
11404 * @wiphy: pointer to wiphy structure
11405 * @dev: pointer to net_device
11406 * @params: pointer to cfg80211_acl_data
11407 *
11408 * Return; 0 on success, error number otherwise
11409 */
11410static int
11411wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
11412 struct net_device *dev,
11413 const struct cfg80211_acl_data *params)
11414{
11415 int ret;
11416
11417 cds_ssr_protect(__func__);
11418 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
11419 cds_ssr_unprotect(__func__);
11420
11421 return ret;
11422}
11423
11424#ifdef WLAN_NL80211_TESTMODE
11425#ifdef FEATURE_WLAN_LPHB
11426/**
11427 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
11428 * @pHddCtx: Pointer to hdd context
11429 * @lphbInd: Pointer to low power heart beat indication parameter
11430 *
11431 * Return: none
11432 */
11433void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
11434{
11435 struct sk_buff *skb;
11436
11437 hddLog(LOGE, FL("LPHB indication arrived"));
11438
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011439 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441
11442 if (NULL == lphbInd) {
11443 hddLog(LOGE, FL("invalid argument lphbInd"));
11444 return;
11445 }
11446
11447 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
11448 wiphy, sizeof(tSirLPHBInd),
11449 GFP_ATOMIC);
11450 if (!skb) {
11451 hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail"));
11452 return;
11453 }
11454
11455 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
11456 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail"));
11457 goto nla_put_failure;
11458 }
11459 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
11460 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail"));
11461 goto nla_put_failure;
11462 }
11463 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
11464 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail"));
11465 goto nla_put_failure;
11466 }
11467 cfg80211_testmode_event(skb, GFP_ATOMIC);
11468 return;
11469
11470nla_put_failure:
11471 hddLog(LOGE, FL("NLA Put fail"));
11472 kfree_skb(skb);
11473
11474 return;
11475}
11476#endif /* FEATURE_WLAN_LPHB */
11477
11478/**
11479 * __wlan_hdd_cfg80211_testmode() - test mode
11480 * @wiphy: Pointer to wiphy
11481 * @data: Data pointer
11482 * @len: Data length
11483 *
11484 * Return: 0 for success, non-zero for failure
11485 */
11486static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
11487 void *data, int len)
11488{
11489 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
11490 int err;
11491 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11492
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011493 ENTER();
11494
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 err = wlan_hdd_validate_context(pHddCtx);
11496 if (err)
11497 return err;
11498
11499 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
11500 len, wlan_hdd_tm_policy);
11501 if (err) {
11502 hddLog(LOGE, FL("Testmode INV ATTR"));
11503 return err;
11504 }
11505
11506 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
11507 hddLog(LOGE, FL("Testmode INV CMD"));
11508 return -EINVAL;
11509 }
11510
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011511 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053011512 TRACE_CODE_HDD_CFG80211_TESTMODE,
11513 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
11515#ifdef FEATURE_WLAN_LPHB
11516 /* Low Power Heartbeat configuration request */
11517 case WLAN_HDD_TM_CMD_WLAN_HB:
11518 {
11519 int buf_len;
11520 void *buf;
11521 tSirLPHBReq *hb_params = NULL;
11522 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011523 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011524
11525 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
11526 hddLog(LOGE, FL("Testmode INV DATA"));
11527 return -EINVAL;
11528 }
11529
11530 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
11531 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
11532
11533 hb_params_temp = (tSirLPHBReq *) buf;
11534 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
11535 && (hb_params_temp->params.lphbTcpParamReq.
11536 timePeriodSec == 0))
11537 return -EINVAL;
11538
11539 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011540 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 if (NULL == hb_params) {
11542 hddLog(LOGE, FL("Request Buffer Alloc Fail"));
11543 return -ENOMEM;
11544 }
11545
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011546 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011547 smeStatus =
11548 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
11549 hb_params,
11550 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011551 if (QDF_STATUS_SUCCESS != smeStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552 hddLog(LOGE, "LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011553 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554 }
11555 return 0;
11556 }
11557#endif /* FEATURE_WLAN_LPHB */
11558
11559#if defined(QCA_WIFI_FTM)
11560 case WLAN_HDD_TM_CMD_WLAN_FTM:
11561 {
11562 int buf_len;
11563 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011564 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
11566 hddLog(LOGE,
11567 FL
11568 ("WLAN_HDD_TM_ATTR_DATA attribute is invalid"));
11569 return -EINVAL;
11570 }
11571
11572 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
11573 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
11574
11575 pr_info("****FTM Tx cmd len = %d*****\n", buf_len);
11576
11577 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
11578
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011579 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011580 err = -EBUSY;
11581 break;
11582 }
11583#endif
11584
11585 default:
11586 hddLog(LOGE, FL("command %d not supported"),
11587 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
11588 return -EOPNOTSUPP;
11589 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011590 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011591 return err;
11592}
11593
11594/**
11595 * wlan_hdd_cfg80211_testmode() - test mode
11596 * @wiphy: Pointer to wiphy
11597 * @dev: Pointer to network device
11598 * @data: Data pointer
11599 * @len: Data length
11600 *
11601 * Return: 0 for success, non-zero for failure
11602 */
11603static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
11604#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11605 struct wireless_dev *wdev,
11606#endif
11607 void *data, int len)
11608{
11609 int ret;
11610
11611 cds_ssr_protect(__func__);
11612 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
11613 cds_ssr_unprotect(__func__);
11614
11615 return ret;
11616}
11617
11618#if defined(QCA_WIFI_FTM)
11619/**
11620 * wlan_hdd_testmode_rx_event() - test mode rx event handler
11621 * @buf: Pointer to buffer
11622 * @buf_len: Buffer length
11623 *
11624 * Return: none
11625 */
11626void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
11627{
11628 struct sk_buff *skb;
11629 hdd_context_t *hdd_ctx;
11630
11631 if (!buf || !buf_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011632 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 "%s: buf or buf_len invalid, buf = %p buf_len = %zu",
11634 __func__, buf, buf_len);
11635 return;
11636 }
11637
Anurag Chouhan6d760662016-02-20 16:05:43 +053011638 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011640 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 "%s: hdd context invalid", __func__);
11642 return;
11643 }
11644
11645 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
11646 buf_len, GFP_KERNEL);
11647 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011648 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 "%s: failed to allocate testmode rx skb!", __func__);
11650 return;
11651 }
11652
11653 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
11654 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
11655 goto nla_put_failure;
11656
11657 pr_info("****FTM Rx cmd len = %zu*****\n", buf_len);
11658
11659 cfg80211_testmode_event(skb, GFP_KERNEL);
11660 return;
11661
11662nla_put_failure:
11663 kfree_skb(skb);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011664 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011665 "%s: nla_put failed on testmode rx skb!", __func__);
11666}
11667#endif
11668#endif /* CONFIG_NL80211_TESTMODE */
11669
11670#ifdef QCA_HT_2040_COEX
11671/**
11672 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11673 * @wiphy: Pointer to wiphy
11674 * @dev: Pointer to network device
11675 * @chandef: Pointer to channel definition parameter
11676 *
11677 * Return: 0 for success, non-zero for failure
11678 */
11679static int
11680__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11681 struct net_device *dev,
11682 struct cfg80211_chan_def *chandef)
11683{
11684 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11685 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011686 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 tSmeConfigParams sme_config;
11688 bool cbModeChange;
11689
Anurag Chouhan6d760662016-02-20 16:05:43 +053011690 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11692 return -EINVAL;
11693 }
11694
11695 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11696 status = wlan_hdd_validate_context(pHddCtx);
11697
11698 if (0 != status) {
11699 hddLog(LOGE, FL("HDD context is not valid"));
11700 return status;
11701 }
11702
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011703 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011704 sme_get_config_param(pHddCtx->hHal, &sme_config);
11705 switch (chandef->width) {
11706 case NL80211_CHAN_WIDTH_20:
11707 if (sme_config.csrConfig.channelBondingMode24GHz !=
11708 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11709 sme_config.csrConfig.channelBondingMode24GHz =
11710 eCSR_INI_SINGLE_CHANNEL_CENTERED;
11711 sme_update_config(pHddCtx->hHal, &sme_config);
11712 cbModeChange = true;
11713 }
11714 break;
11715
11716 case NL80211_CHAN_WIDTH_40:
11717 if (sme_config.csrConfig.channelBondingMode24GHz ==
11718 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11719 if (NL80211_CHAN_HT40MINUS ==
11720 cfg80211_get_chandef_type(chandef))
11721 sme_config.csrConfig.channelBondingMode24GHz =
11722 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
11723 else
11724 sme_config.csrConfig.channelBondingMode24GHz =
11725 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
11726 sme_update_config(pHddCtx->hHal, &sme_config);
11727 cbModeChange = true;
11728 }
11729 break;
11730
11731 default:
11732 hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !"));
11733 return -EINVAL;
11734 }
11735
11736 if (!cbModeChange)
11737 return 0;
11738
Krunal Sonib4326f22016-03-10 13:05:51 -080011739 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 return 0;
11741
11742 hddLog(LOG1, FL("Channel bonding changed to %d"),
11743 sme_config.csrConfig.channelBondingMode24GHz);
11744
11745 /* Change SAP ht2040 mode */
11746 status = hdd_set_sap_ht2040_mode(pAdapter,
11747 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011748 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 hddLog(LOGE, FL("Error!!! Cannot set SAP HT20/40 mode!"));
11750 return -EINVAL;
11751 }
11752
11753 return 0;
11754}
11755
11756/**
11757 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11758 * @wiphy: Pointer to wiphy
11759 * @dev: Pointer to network device
11760 * @chandef: Pointer to channel definition parameter
11761 *
11762 * Return: 0 for success, non-zero for failure
11763 */
11764static int
11765wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11766 struct net_device *dev,
11767 struct cfg80211_chan_def *chandef)
11768{
11769 int ret;
11770
11771 cds_ssr_protect(__func__);
11772 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
11773 cds_ssr_unprotect(__func__);
11774
11775 return ret;
11776}
11777#endif
11778
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011779#ifdef CHANNEL_SWITCH_SUPPORTED
11780/**
11781 * __wlan_hdd_cfg80211_channel_switch()- function to switch
11782 * channel in SAP/GO
11783 * @wiphy: wiphy pointer
11784 * @dev: dev pointer.
11785 * @csa_params: Change channel params
11786 *
11787 * This function is called to switch channel in SAP/GO
11788 *
11789 * Return: 0 if success else return non zero
11790 */
11791static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11792 struct net_device *dev,
11793 struct cfg80211_csa_settings *csa_params)
11794{
11795 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
11796 hdd_context_t *hdd_ctx;
11797 uint8_t channel;
11798 uint16_t freq;
11799 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080011800 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011801
11802 hddLog(LOG1, FL("Set Freq %d"),
11803 csa_params->chandef.chan->center_freq);
11804
11805 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11806 ret = wlan_hdd_validate_context(hdd_ctx);
11807
11808 if (0 != ret)
11809 return ret;
11810
Krunal Sonib4326f22016-03-10 13:05:51 -080011811 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
11812 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011813 return -ENOTSUPP;
11814
11815 freq = csa_params->chandef.chan->center_freq;
11816 channel = cds_freq_to_chan(freq);
11817
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053011818 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
11819
11820 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011821 return ret;
11822}
11823
11824/**
11825 * wlan_hdd_cfg80211_channel_switch()- function to switch
11826 * channel in SAP/GO
11827 * @wiphy: wiphy pointer
11828 * @dev: dev pointer.
11829 * @csa_params: Change channel params
11830 *
11831 * This function is called to switch channel in SAP/GO
11832 *
11833 * Return: 0 if success else return non zero
11834 */
11835static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11836 struct net_device *dev,
11837 struct cfg80211_csa_settings *csa_params)
11838{
11839 int ret;
11840
11841 cds_ssr_protect(__func__);
11842 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
11843 cds_ssr_unprotect(__func__);
11844 return ret;
11845}
11846#endif
11847
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848/**
11849 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
11850 * translation from NL to policy manager type
11851 * @type: Generic connection mode type defined in NL
11852 *
11853 *
11854 * This function provides the type translation
11855 *
11856 * Return: cds_con_mode enum
11857 */
11858enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
11859 enum nl80211_iftype type)
11860{
11861 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
11862 switch (type) {
11863 case NL80211_IFTYPE_STATION:
11864 mode = CDS_STA_MODE;
11865 break;
11866 case NL80211_IFTYPE_P2P_CLIENT:
11867 mode = CDS_P2P_CLIENT_MODE;
11868 break;
11869 case NL80211_IFTYPE_P2P_GO:
11870 mode = CDS_P2P_GO_MODE;
11871 break;
11872 case NL80211_IFTYPE_AP:
11873 mode = CDS_SAP_MODE;
11874 break;
11875 case NL80211_IFTYPE_ADHOC:
11876 mode = CDS_IBSS_MODE;
11877 break;
11878 default:
11879 hddLog(LOGE, FL("Unsupported interface type (%d)"),
11880 type);
11881 }
11882 return mode;
11883}
11884
11885/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011886 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
11887 * @wiphy: Handle to struct wiphy to get handle to module context.
11888 * @chandef: Contains information about the capture channel to be set.
11889 *
11890 * This interface is called if and only if monitor mode interface alone is
11891 * active.
11892 *
11893 * Return: 0 success or error code on failure.
11894 */
11895static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
11896 struct cfg80211_chan_def *chandef)
11897{
11898 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
11899 hdd_adapter_t *adapter;
11900 hdd_station_ctx_t *sta_ctx;
11901 struct hdd_mon_set_ch_info *ch_info;
11902 QDF_STATUS status;
11903 tHalHandle hal_hdl;
11904 struct qdf_mac_addr bssid;
11905 tCsrRoamProfile roam_profile;
11906 struct ch_params_s ch_params;
11907 int ret;
11908 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
11909
11910 ENTER();
11911
11912 ret = wlan_hdd_validate_context(hdd_ctx);
11913 if (ret)
11914 return ret;
11915
11916 hal_hdl = hdd_ctx->hHal;
11917
11918 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
11919 if (!adapter)
11920 return -EIO;
11921
11922 hdd_info("%s: set monitor mode Channel %d and freq %d",
11923 adapter->dev->name, chan_num, chandef->chan->center_freq);
11924
11925 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
11926 ch_info = &sta_ctx->ch_info;
11927 hdd_select_cbmode(adapter, chan_num);
11928 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
11929 roam_profile.ChannelInfo.numOfChannels = 1;
11930 roam_profile.phyMode = ch_info->phy_mode;
11931 roam_profile.ch_params.ch_width = chandef->width;
11932
11933 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
11934 QDF_MAC_ADDR_SIZE);
11935
11936 ch_params.ch_width = chandef->width;
11937 sme_set_ch_params(hal_hdl, ch_info->phy_mode, chan_num, 0,
11938 &ch_params);
11939 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
11940 &roam_profile);
11941 if (status) {
11942 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
11943 status);
11944 ret = qdf_status_to_os_return(status);
11945 return ret;
11946 }
11947 EXIT();
11948 return 0;
11949}
11950
11951/**
11952 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
11953 * @wiphy: Handle to struct wiphy to get handle to module context.
11954 * @chandef: Contains information about the capture channel to be set.
11955 *
11956 * This interface is called if and only if monitor mode interface alone is
11957 * active.
11958 *
11959 * Return: 0 success or error code on failure.
11960 */
11961static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
11962 struct cfg80211_chan_def *chandef)
11963{
11964 int ret;
11965
11966 cds_ssr_protect(__func__);
11967 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
11968 cds_ssr_unprotect(__func__);
11969 return ret;
11970}
11971
11972/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011973 * struct cfg80211_ops - cfg80211_ops
11974 *
11975 * @add_virtual_intf: Add virtual interface
11976 * @del_virtual_intf: Delete virtual interface
11977 * @change_virtual_intf: Change virtual interface
11978 * @change_station: Change station
11979 * @add_beacon: Add beacon in sap mode
11980 * @del_beacon: Delete beacon in sap mode
11981 * @set_beacon: Set beacon in sap mode
11982 * @start_ap: Start ap
11983 * @change_beacon: Change beacon
11984 * @stop_ap: Stop ap
11985 * @change_bss: Change bss
11986 * @add_key: Add key
11987 * @get_key: Get key
11988 * @del_key: Delete key
11989 * @set_default_key: Set default key
11990 * @set_channel: Set channel
11991 * @scan: Scan
11992 * @connect: Connect
11993 * @disconnect: Disconnect
11994 * @join_ibss = Join ibss
11995 * @leave_ibss = Leave ibss
11996 * @set_wiphy_params = Set wiphy params
11997 * @set_tx_power = Set tx power
11998 * @get_tx_power = get tx power
11999 * @remain_on_channel = Remain on channel
12000 * @cancel_remain_on_channel = Cancel remain on channel
12001 * @mgmt_tx = Tx management frame
12002 * @mgmt_tx_cancel_wait = Cancel management tx wait
12003 * @set_default_mgmt_key = Set default management key
12004 * @set_txq_params = Set tx queue parameters
12005 * @get_station = Get station
12006 * @set_power_mgmt = Set power management
12007 * @del_station = Delete station
12008 * @add_station = Add station
12009 * @set_pmksa = Set pmksa
12010 * @del_pmksa = Delete pmksa
12011 * @flush_pmksa = Flush pmksa
12012 * @update_ft_ies = Update FT IEs
12013 * @tdls_mgmt = Tdls management
12014 * @tdls_oper = Tdls operation
12015 * @set_rekey_data = Set rekey data
12016 * @sched_scan_start = Scheduled scan start
12017 * @sched_scan_stop = Scheduled scan stop
12018 * @resume = Resume wlan
12019 * @suspend = Suspend wlan
12020 * @set_mac_acl = Set mac acl
12021 * @testmode_cmd = Test mode command
12022 * @set_ap_chanwidth = Set AP channel bandwidth
12023 * @dump_survey = Dump survey
12024 * @key_mgmt_set_pmk = Set pmk key management
12025 */
12026static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
12027 .add_virtual_intf = wlan_hdd_add_virtual_intf,
12028 .del_virtual_intf = wlan_hdd_del_virtual_intf,
12029 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
12030 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031 .start_ap = wlan_hdd_cfg80211_start_ap,
12032 .change_beacon = wlan_hdd_cfg80211_change_beacon,
12033 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012034 .change_bss = wlan_hdd_cfg80211_change_bss,
12035 .add_key = wlan_hdd_cfg80211_add_key,
12036 .get_key = wlan_hdd_cfg80211_get_key,
12037 .del_key = wlan_hdd_cfg80211_del_key,
12038 .set_default_key = wlan_hdd_cfg80211_set_default_key,
12039 .scan = wlan_hdd_cfg80211_scan,
12040 .connect = wlan_hdd_cfg80211_connect,
12041 .disconnect = wlan_hdd_cfg80211_disconnect,
12042 .join_ibss = wlan_hdd_cfg80211_join_ibss,
12043 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
12044 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
12045 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
12046 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
12047 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
12048 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
12049 .mgmt_tx = wlan_hdd_mgmt_tx,
12050 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
12051 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
12052 .set_txq_params = wlan_hdd_set_txq_params,
12053 .get_station = wlan_hdd_cfg80211_get_station,
12054 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
12055 .del_station = wlan_hdd_cfg80211_del_station,
12056 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012057 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
12058 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
12059 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080012060#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
12062#endif
12063#ifdef FEATURE_WLAN_TDLS
12064 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
12065 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
12066#endif
12067#ifdef WLAN_FEATURE_GTK_OFFLOAD
12068 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
12069#endif /* WLAN_FEATURE_GTK_OFFLOAD */
12070#ifdef FEATURE_WLAN_SCAN_PNO
12071 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
12072 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
12073#endif /*FEATURE_WLAN_SCAN_PNO */
12074 .resume = wlan_hdd_cfg80211_resume_wlan,
12075 .suspend = wlan_hdd_cfg80211_suspend_wlan,
12076 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
12077#ifdef WLAN_NL80211_TESTMODE
12078 .testmode_cmd = wlan_hdd_cfg80211_testmode,
12079#endif
12080#ifdef QCA_HT_2040_COEX
12081 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
12082#endif
12083 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012084#ifdef CHANNEL_SWITCH_SUPPORTED
12085 .channel_switch = wlan_hdd_cfg80211_channel_switch,
12086#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012087 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012088};