blob: cdf0e41d7fde4c05f97e6649891c8466e8f558e5 [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
508static struct ieee80211_iface_combination
509 wlan_hdd_iface_combination[] = {
510 /* STA */
511 {
512 .limits = wlan_hdd_sta_iface_limit,
513 .num_different_channels = 2,
514 .max_interfaces = 3,
515 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
516 },
517 /* ADHOC */
518 {
519 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700520 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521 .max_interfaces = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
523 },
524 /* AP */
525 {
526 .limits = wlan_hdd_ap_iface_limit,
527 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
530 },
531 /* P2P */
532 {
533 .limits = wlan_hdd_p2p_iface_limit,
534 .num_different_channels = 2,
535 .max_interfaces = 2,
536 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
537 },
538 /* STA + AP */
539 {
540 .limits = wlan_hdd_sta_ap_iface_limit,
541 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530542 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
544 .beacon_int_infra_match = true,
545 },
546 /* STA + P2P */
547 {
548 .limits = wlan_hdd_sta_p2p_iface_limit,
549 .num_different_channels = 2,
550 /* one interface reserved for P2PDEV dedicated usage */
551 .max_interfaces = 4,
552 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
553 .beacon_int_infra_match = true,
554 },
555 /* STA + P2P GO + SAP */
556 {
557 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
558 /* we can allow 3 channels for three different persona
559 * but due to firmware limitation, allow max 2 concrnt channels.
560 */
561 .num_different_channels = 2,
562 /* one interface reserved for P2PDEV dedicated usage */
563 .max_interfaces = 4,
564 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
565 .beacon_int_infra_match = true,
566 },
567 /* SAP + P2P */
568 {
569 .limits = wlan_hdd_sap_p2p_iface_limit,
570 .num_different_channels = 2,
571 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
572 .max_interfaces = 3,
573 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
574 .beacon_int_infra_match = true,
575 },
576 /* P2P + P2P */
577 {
578 .limits = wlan_hdd_p2p_p2p_iface_limit,
579 .num_different_channels = 2,
580 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
581 .max_interfaces = 3,
582 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
583 .beacon_int_infra_match = true,
584 },
585};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800586
587static struct cfg80211_ops wlan_hdd_cfg80211_ops;
588
589
590#ifdef WLAN_NL80211_TESTMODE
591enum wlan_hdd_tm_attr {
592 WLAN_HDD_TM_ATTR_INVALID = 0,
593 WLAN_HDD_TM_ATTR_CMD = 1,
594 WLAN_HDD_TM_ATTR_DATA = 2,
595 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
596 WLAN_HDD_TM_ATTR_TYPE = 4,
597 /* keep last */
598 WLAN_HDD_TM_ATTR_AFTER_LAST,
599 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
600};
601
602enum wlan_hdd_tm_cmd {
603 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
604 WLAN_HDD_TM_CMD_WLAN_HB = 1,
605};
606
607#define WLAN_HDD_TM_DATA_MAX_LEN 5000
608
609static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
610 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
611 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
612 .len = WLAN_HDD_TM_DATA_MAX_LEN},
613};
614#endif /* WLAN_NL80211_TESTMODE */
615
616#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
617static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
618 .flags = WIPHY_WOWLAN_MAGIC_PKT,
619 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
620 .pattern_min_len = 1,
621 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
622};
623#endif
624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530626 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
627 * @flags: Pointer to the flags to Add channel switch flag.
628 *
629 * This Function adds Channel Switch support flag, if channel switch is
630 * supported by kernel.
631 * Return: void.
632 */
633#ifdef CHANNEL_SWITCH_SUPPORTED
634static inline void hdd_add_channel_switch_support(uint32_t *flags)
635{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800636 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530637 return;
638}
639#else
640static inline void hdd_add_channel_switch_support(uint32_t *flags)
641{
642 return;
643}
644#endif
645
Manikandan Mohan22b83722015-12-15 15:03:23 -0800646#ifdef FEATURE_WLAN_TDLS
647
648/* TDLS capabilities params */
649#define PARAM_MAX_TDLS_SESSION \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
651#define PARAM_TDLS_FEATURE_SUPPORT \
652 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
653
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530654/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
656 * @wiphy: WIPHY structure pointer
657 * @wdev: Wireless device structure pointer
658 * @data: Pointer to the data received
659 * @data_len: Length of the data received
660 *
661 * This function provides TDLS capabilities
662 *
663 * Return: 0 on success and errno on failure
664 */
665static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
666 struct wireless_dev *wdev,
667 const void *data,
668 int data_len)
669{
670 int status;
671 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
672 struct sk_buff *skb;
673 uint32_t set = 0;
674
Jeff Johnson1f61b612016-02-12 16:28:33 -0800675 ENTER_DEV(wdev->netdev);
676
Anurag Chouhan6d760662016-02-20 16:05:43 +0530677 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 hdd_err("Command not allowed in FTM mode");
679 return -EPERM;
680 }
681
682 status = wlan_hdd_validate_context(hdd_ctx);
683 if (status)
684 return status;
685
686 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
687 NLMSG_HDRLEN);
688 if (!skb) {
689 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
690 goto fail;
691 }
692
693 if (false == hdd_ctx->config->fEnableTDLSSupport) {
694 hddLog(LOGE,
695 FL("TDLS feature not Enabled or Not supported in FW"));
696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
698 hddLog(LOGE, FL("nla put fail"));
699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
707 hddLog(LOG1, FL("TDLS Feature supported value %x"), set);
708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
712 hddLog(LOGE, FL("nla put fail"));
713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
769 hddLog(LOGE, FL("HDD context is null"));
770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
774 hddLog(LOGE, FL("pAvoidFreqList is null"));
775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
784 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
1063 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1066 },
1067 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1068 .vendor_id = QCA_NL80211_VENDOR_ID,
1069 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1070 },
1071 /* OCB events */
1072 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1073 .vendor_id = QCA_NL80211_VENDOR_ID,
1074 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1075 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001076#ifdef FEATURE_LFR_SUBNET_DETECTION
1077 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1078 .vendor_id = QCA_NL80211_VENDOR_ID,
1079 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1080 },
1081#endif /*FEATURE_LFR_SUBNET_DETECTION */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082};
1083
1084/**
1085 * __is_driver_dfs_capable() - get driver DFS capability
1086 * @wiphy: pointer to wireless wiphy structure.
1087 * @wdev: pointer to wireless_dev structure.
1088 * @data: Pointer to the data to be passed via vendor interface
1089 * @data_len:Length of the data to be passed
1090 *
1091 * This function is called by userspace to indicate whether or not
1092 * the driver supports DFS offload.
1093 *
1094 * Return: 0 on success, negative errno on failure
1095 */
1096static int __is_driver_dfs_capable(struct wiphy *wiphy,
1097 struct wireless_dev *wdev,
1098 const void *data,
1099 int data_len)
1100{
1101 u32 dfs_capability = 0;
1102 struct sk_buff *temp_skbuff;
1103 int ret_val;
1104 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1105
Jeff Johnson1f61b612016-02-12 16:28:33 -08001106 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107
1108 ret_val = wlan_hdd_validate_context(hdd_ctx);
1109 if (ret_val)
1110 return ret_val;
1111
Anurag Chouhan6d760662016-02-20 16:05:43 +05301112 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001113 hdd_err("Command not allowed in FTM mode");
1114 return -EPERM;
1115 }
1116
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001118
1119 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1120 NLMSG_HDRLEN);
1121
1122 if (temp_skbuff != NULL) {
1123 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1124 dfs_capability);
1125 if (ret_val) {
1126 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail"));
1127 kfree_skb(temp_skbuff);
1128
1129 return ret_val;
1130 }
1131
1132 return cfg80211_vendor_cmd_reply(temp_skbuff);
1133 }
1134
1135 hddLog(LOGE, FL("dfs capability: buffer alloc fail"));
1136 return -ENOMEM;
1137}
1138
1139/**
1140 * is_driver_dfs_capable() - get driver DFS capability
1141 * @wiphy: pointer to wireless wiphy structure.
1142 * @wdev: pointer to wireless_dev structure.
1143 * @data: Pointer to the data to be passed via vendor interface
1144 * @data_len:Length of the data to be passed
1145 *
1146 * This function is called by userspace to indicate whether or not
1147 * the driver supports DFS offload. This is an SSR-protected
1148 * wrapper function.
1149 *
1150 * Return: 0 on success, negative errno on failure
1151 */
1152static int is_driver_dfs_capable(struct wiphy *wiphy,
1153 struct wireless_dev *wdev,
1154 const void *data,
1155 int data_len)
1156{
1157 int ret;
1158
1159 cds_ssr_protect(__func__);
1160 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1161 cds_ssr_unprotect(__func__);
1162
1163 return ret;
1164}
1165
1166/**
1167 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1168 *
1169 * @adapter: SAP adapter pointer
1170 *
1171 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1172 * radio. So in case of DFS MCC scenario override current SAP given config
1173 * to follow concurrent SAP DFS config
1174 *
1175 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1176 */
1177
1178#ifdef WLAN_FEATURE_MBSSID
1179int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1180{
1181 hdd_adapter_t *con_sap_adapter;
1182 tsap_Config_t *sap_config, *con_sap_config;
1183 int con_ch;
1184
1185 /*
1186 * Check if AP+AP case, once primary AP chooses a DFS
1187 * channel secondary AP should always follow primary APs channel
1188 */
1189 if (!cds_concurrent_beaconing_sessions_running())
1190 return 0;
1191
1192 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1193 if (!con_sap_adapter)
1194 return 0;
1195
1196 sap_config = &adapter->sessionCtx.ap.sapConfig;
1197 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1198 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1199
1200 if (!CDS_IS_DFS_CH(con_ch))
1201 return 0;
1202
1203 hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"),
1204 sap_config->channel, con_ch);
1205 hddLog(LOG1, FL("Overriding guest AP's channel"));
1206 sap_config->channel = con_ch;
1207
1208 if (con_sap_config->acs_cfg.acs_mode == true) {
1209 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1210 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
1211 hddLog(LOGE, FL("Primary AP channel config error"));
1212 hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"),
1213 con_ch, con_sap_config->acs_cfg.pri_ch,
1214 con_sap_config->acs_cfg.ht_sec_ch);
1215 return -EINVAL;
1216 }
1217 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1218 * MCC restriction. So free ch list allocated in do_acs
1219 * func for Sec AP and realloc for Pri AP ch list size
1220 */
1221 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301222 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301224 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 &con_sap_config->acs_cfg,
1226 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301227 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001228 sizeof(uint8_t) *
1229 con_sap_config->acs_cfg.ch_list_count);
1230 if (!sap_config->acs_cfg.ch_list) {
1231 hddLog(LOGE, FL("ACS config alloc fail"));
1232 return -ENOMEM;
1233 }
1234
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301235 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 con_sap_config->acs_cfg.ch_list,
1237 con_sap_config->acs_cfg.ch_list_count);
1238
1239 } else {
1240 sap_config->acs_cfg.pri_ch = con_ch;
1241 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1242 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1243 }
1244
1245 return con_ch;
1246}
1247#else
1248int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1249{
1250 return 0;
1251}
1252#endif
1253
1254/**
1255 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1256 * @sap_cfg: pointer to SAP config struct
1257 *
1258 * This function sets the default ACS start and end channel for the given band
1259 * and also parses the given ACS channel list.
1260 *
1261 * Return: None
1262 */
1263
1264static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1265 bool vht_enabled)
1266{
1267 int i;
1268 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1269 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001270 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1271 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1273 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001274 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1275 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1277 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001278 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1279 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001280 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1281 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001282 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1283 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001284 }
1285
1286 if (ht_enabled)
1287 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1288
1289 if (vht_enabled)
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1291
1292
1293 /* Parse ACS Chan list from hostapd */
1294 if (!sap_cfg->acs_cfg.ch_list)
1295 return;
1296
1297 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1298 sap_cfg->acs_cfg.end_ch =
1299 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1300 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
1301 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i])
1302 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1303 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1304 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1305 }
1306}
1307
1308
1309static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1310
1311/**
1312 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1313 * @adapter: pointer to SAP adapter struct
1314 *
1315 * This function starts the ACS procedure if there are no
1316 * constraints like MBSSID DFS restrictions.
1317 *
1318 * Return: Status of ACS Start procedure
1319 */
1320
1321static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1322{
1323
1324 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1325 tsap_Config_t *sap_config;
1326 tpWLAN_SAPEventCB acs_event_callback;
1327 int status;
1328
1329 sap_config = &adapter->sessionCtx.ap.sapConfig;
1330 sap_config->channel = AUTO_CHANNEL_SELECT;
1331
1332 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1333 if (status < 0) {
1334 return status;
1335 } else {
1336 if (status > 0) {
1337 /*notify hostapd about channel override */
1338 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1339 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1340 return 0;
1341 }
1342 }
1343 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1344 if (status) {
1345 hddLog(LOGE, FL("ACS config failed"));
1346 return -EINVAL;
1347 }
1348
1349 acs_event_callback = hdd_hostapd_sap_event_cb;
1350
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301351 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301352 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353 hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex);
1354 status = wlansap_acs_chselect(
1355#ifdef WLAN_FEATURE_MBSSID
1356 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1357#else
1358 hdd_ctx->pcds_context,
1359#endif
1360 acs_event_callback, sap_config, adapter->dev);
1361
1362
1363 if (status) {
1364 hddLog(LOGE, FL("ACS channel select failed"));
1365 return -EINVAL;
1366 }
1367 sap_config->acs_cfg.acs_mode = true;
1368 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1369
1370 return 0;
1371}
1372
1373/**
1374 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1375 * @wiphy: Linux wiphy struct pointer
1376 * @wdev: Linux wireless device struct pointer
1377 * @data: ACS information from hostapd
1378 * @data_len: ACS information length
1379 *
1380 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1381 * and starts ACS procedure.
1382 *
1383 * Return: ACS procedure start status
1384 */
1385
1386static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1387 struct wireless_dev *wdev,
1388 const void *data, int data_len)
1389{
1390 struct net_device *ndev = wdev->netdev;
1391 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1392 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1393 tsap_Config_t *sap_config;
1394 struct sk_buff *temp_skbuff;
1395 int status = -EINVAL, i = 0;
1396 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1397 bool ht_enabled, ht40_enabled, vht_enabled;
1398 uint8_t ch_width;
1399
1400 /* ***Note*** Donot set SME config related to ACS operation here because
1401 * ACS operation is not synchronouse and ACS for Second AP may come when
1402 * ACS operation for first AP is going on. So only do_acs is split to
1403 * seperate start_acs routine. Also SME-PMAC struct that is used to
1404 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1405 * config shall be set only from start_acs.
1406 */
1407
1408 /* nla_policy Policy template. Policy not applied as some attributes are
1409 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1410 *
1411 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1412 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1413 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1414 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1415 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1416 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1417 */
1418
Jeff Johnson1f61b612016-02-12 16:28:33 -08001419 ENTER_DEV(ndev);
1420
Anurag Chouhan6d760662016-02-20 16:05:43 +05301421 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001422 hdd_err("Command not allowed in FTM mode");
1423 return -EPERM;
1424 }
1425
1426 if (hdd_ctx->config->force_sap_acs) {
1427 hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled"));
1428 return -EPERM;
1429 }
1430
1431 status = wlan_hdd_validate_context(hdd_ctx);
1432 if (0 != status) {
1433 hddLog(LOGE, FL("HDD context is not valid"));
1434 goto out;
1435 }
1436 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301437 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438
1439 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1440 NULL);
1441 if (status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301442 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 goto out;
1444 }
1445
1446 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301447 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 goto out;
1449 }
1450 sap_config->acs_cfg.hw_mode = nla_get_u8(
1451 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1452
1453 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1454 ht_enabled =
1455 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1456 else
1457 ht_enabled = 0;
1458
1459 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1460 ht40_enabled =
1461 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1462 else
1463 ht40_enabled = 0;
1464
1465 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1466 vht_enabled =
1467 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1468 else
1469 vht_enabled = 0;
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1472 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1473 } else {
1474 if (ht_enabled && ht40_enabled)
1475 ch_width = 40;
1476 else
1477 ch_width = 20;
1478 }
1479 if (ch_width == 80)
1480 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1481 else if (ch_width == 40)
1482 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1483 else
1484 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1485
1486 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1487 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1488 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1489 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1490 * since it contains the frequency values of the channels in
1491 * the channel list.
1492 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1493 * is present
1494 */
1495 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1496 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1497 sap_config->acs_cfg.ch_list_count = nla_len(
1498 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1499 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301500 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 sizeof(uint8_t) *
1502 sap_config->acs_cfg.ch_list_count);
1503 if (sap_config->acs_cfg.ch_list == NULL)
1504 goto out;
1505
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301506 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507 sap_config->acs_cfg.ch_list_count);
1508 }
1509 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1510 uint32_t *freq =
1511 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1512 sap_config->acs_cfg.ch_list_count = nla_len(
1513 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1514 sizeof(uint32_t);
1515 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301516 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517 sap_config->acs_cfg.ch_list_count);
1518 if (sap_config->acs_cfg.ch_list == NULL) {
1519 hddLog(LOGE, FL("ACS config alloc fail"));
1520 status = -ENOMEM;
1521 goto out;
1522 }
1523
1524 /* convert frequency to channel */
1525 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1526 sap_config->acs_cfg.ch_list[i] =
1527 ieee80211_frequency_to_channel(freq[i]);
1528 }
1529 }
1530
1531 hdd_debug("get pcl for DO_ACS vendor command");
1532
1533 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001534 status = cds_get_pcl(CDS_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 sap_config->acs_cfg.pcl_channels,
1536 &sap_config->acs_cfg.pcl_ch_count);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301537 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 hddLog(LOGE, FL("Get PCL failed"));
1539
1540 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1541
1542 /* ACS override for android */
1543 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
1544 hddLog(LOG1, FL("ACS Config override for 11AC"));
1545 vht_enabled = 1;
1546 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1547 sap_config->acs_cfg.ch_width =
1548 hdd_ctx->config->vhtChannelWidth;
1549 /* No VHT80 in 2.4G so perform ACS accordingly */
1550 if (sap_config->acs_cfg.end_ch <= 14 &&
1551 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1552 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1553 }
1554
1555 hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"),
1556 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1557 ch_width, ht_enabled, vht_enabled,
1558 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1559
1560 if (sap_config->acs_cfg.ch_list_count) {
1561 hddLog(LOG1, FL("ACS channel list: len: %d"),
1562 sap_config->acs_cfg.ch_list_count);
1563 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1564 hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]);
1565 }
1566 sap_config->acs_cfg.acs_mode = true;
1567 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
1568 /* ***Note*** Completion variable usage is not allowed here since
1569 * ACS scan operation may take max 2.2 sec for 5G band.
1570 * 9 Active channel X 40 ms active scan time +
1571 * 16 Passive channel X 110ms passive scan time
1572 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1573 * for this long. So we split up the scanning part.
1574 */
1575 set_bit(ACS_PENDING, &adapter->event_flags);
1576 hddLog(LOG1, FL("ACS Pending for wlan%d"),
1577 adapter->dev->ifindex);
1578 status = 0;
1579 } else {
1580 status = wlan_hdd_cfg80211_start_acs(adapter);
1581 }
1582
1583out:
1584 if (0 == status) {
1585 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1586 NLMSG_HDRLEN);
1587 if (temp_skbuff != NULL)
1588 return cfg80211_vendor_cmd_reply(temp_skbuff);
1589 }
1590
1591 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1592
1593 return status;
1594}
1595
1596 /**
1597 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1598 * @wiphy: Linux wiphy struct pointer
1599 * @wdev: Linux wireless device struct pointer
1600 * @data: ACS information from hostapd
1601 * @data_len: ACS information len
1602 *
1603 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1604 * and starts ACS procedure.
1605 *
1606 * Return: ACS procedure start status
1607 */
1608
1609static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1610 struct wireless_dev *wdev,
1611 const void *data, int data_len)
1612{
1613 int ret;
1614
1615 cds_ssr_protect(__func__);
1616 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1617 cds_ssr_unprotect(__func__);
1618
1619 return ret;
1620}
1621
1622/**
1623 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1624 * @work: Linux workqueue struct pointer for ACS work
1625 *
1626 * This function starts the ACS procedure which was marked pending when an ACS
1627 * procedure was in progress for a concurrent SAP interface.
1628 *
1629 * Return: None
1630 */
1631
1632static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1633{
1634 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1635 acs_pending_work.work);
1636 wlan_hdd_cfg80211_start_acs(adapter);
1637}
1638
1639/**
1640 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1641 * @adapter: Pointer to SAP adapter struct
1642 * @pri_channel: SAP ACS procedure selected Primary channel
1643 * @sec_channel: SAP ACS procedure selected secondary channel
1644 *
1645 * This is a callback function from SAP module on ACS procedure is completed.
1646 * This function send the ACS selected channel information to hostapd
1647 *
1648 * Return: None
1649 */
1650
1651void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1652{
1653 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1654 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1655 struct sk_buff *vendor_event;
1656 int ret_val;
1657 hdd_adapter_t *con_sap_adapter;
1658 uint16_t ch_width;
1659
1660 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001661 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1663 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1664 GFP_KERNEL);
1665
1666 if (!vendor_event) {
1667 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
1668 return;
1669 }
1670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671 ret_val = nla_put_u8(vendor_event,
1672 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1673 sap_cfg->acs_cfg.pri_ch);
1674 if (ret_val) {
1675 hddLog(LOGE,
1676 FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail"));
1677 kfree_skb(vendor_event);
1678 return;
1679 }
1680
1681 ret_val = nla_put_u8(vendor_event,
1682 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1683 sap_cfg->acs_cfg.ht_sec_ch);
1684 if (ret_val) {
1685 hddLog(LOGE,
1686 FL(
1687 "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail"));
1688 kfree_skb(vendor_event);
1689 return;
1690 }
1691
1692 ret_val = nla_put_u8(vendor_event,
1693 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1694 sap_cfg->acs_cfg.vht_seg0_center_ch);
1695 if (ret_val) {
1696 hddLog(LOGE,
1697 FL(
1698 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail"));
1699 kfree_skb(vendor_event);
1700 return;
1701 }
1702
1703 ret_val = nla_put_u8(vendor_event,
1704 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1705 sap_cfg->acs_cfg.vht_seg1_center_ch);
1706 if (ret_val) {
1707 hddLog(LOGE,
1708 FL(
1709 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail"));
1710 kfree_skb(vendor_event);
1711 return;
1712 }
1713
1714 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1715 ch_width = 80;
1716 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1717 ch_width = 40;
1718 else
1719 ch_width = 20;
1720
1721 ret_val = nla_put_u16(vendor_event,
1722 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1723 ch_width);
1724 if (ret_val) {
1725 hddLog(LOGE,
1726 FL(
1727 "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail"));
1728 kfree_skb(vendor_event);
1729 return;
1730 }
1731 if (sap_cfg->acs_cfg.pri_ch > 14)
1732 ret_val = nla_put_u8(vendor_event,
1733 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1734 QCA_ACS_MODE_IEEE80211A);
1735 else
1736 ret_val = nla_put_u8(vendor_event,
1737 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1738 QCA_ACS_MODE_IEEE80211G);
1739
1740 if (ret_val) {
1741 hddLog(LOGE,
1742 FL(
1743 "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail"));
1744 kfree_skb(vendor_event);
1745 return;
1746 }
1747
1748 hddLog(LOG1,
1749 FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"),
1750 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1751 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1752 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1753
1754 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1755 /* ***Note*** As already mentioned Completion variable usage is not
1756 * allowed here since ACS scan operation may take max 2.2 sec.
1757 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1758 * operation.
1759 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1760 * when Primary AP ACS is complete and secondary AP ACS is started here
1761 * immediately, Primary AP start_bss may come inbetween ACS operation
1762 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1763 * delay. This path and below constraint will be removed on sessionizing
1764 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1765 * As per design constraint user space control application must take
1766 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1767 * this code path. Sec AP hostapd should be started after Primary AP
1768 * start beaconing which can be confirmed by getchannel iwpriv command
1769 */
1770
1771 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1772 if (con_sap_adapter &&
1773 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
1774#ifdef CONFIG_CNSS
1775 cnss_init_delayed_work(&con_sap_adapter->acs_pending_work,
1776 wlan_hdd_cfg80211_start_pending_acs);
1777#else
1778 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1779 wlan_hdd_cfg80211_start_pending_acs);
1780#endif
1781 /* Lets give 500ms for OBSS + START_BSS to complete */
1782 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1783 msecs_to_jiffies(500));
1784 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1785 }
1786
1787 return;
1788}
1789
1790static int
1791__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1792 struct wireless_dev *wdev,
1793 const void *data,
1794 int data_len)
1795{
1796 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1797 struct sk_buff *skb = NULL;
1798 uint32_t fset = 0;
1799 int ret;
1800
Jeff Johnson1f61b612016-02-12 16:28:33 -08001801 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301802
Anurag Chouhan6d760662016-02-20 16:05:43 +05301803 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 hdd_err("Command not allowed in FTM mode");
1805 return -EPERM;
1806 }
1807
1808 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301809 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001811
1812 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
1813 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
1814 fset |= WIFI_FEATURE_INFRA;
1815 }
1816 if (true == hdd_is_5g_supported(pHddCtx)) {
1817 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
1818 fset |= WIFI_FEATURE_INFRA_5G;
1819 }
1820#ifdef WLAN_FEATURE_P2P
1821 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1822 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
1823 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
1824 fset |= WIFI_FEATURE_P2P;
1825 }
1826#endif
1827 fset |= WIFI_FEATURE_SOFT_AP;
1828
1829 /* HOTSPOT is a supplicant feature, enable it by default */
1830 fset |= WIFI_FEATURE_HOTSPOT;
1831
1832#ifdef FEATURE_WLAN_EXTSCAN
1833 if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
1834 hddLog(LOG1, FL("EXTScan is supported by firmware"));
1835 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1836 }
1837#endif
1838 if (wlan_hdd_nan_is_supported()) {
1839 hddLog(LOG1, FL("NAN is supported by firmware"));
1840 fset |= WIFI_FEATURE_NAN;
1841 }
1842 if (sme_is_feature_supported_by_fw(RTT)) {
1843 hddLog(LOG1, FL("RTT is supported by firmware"));
1844 fset |= WIFI_FEATURE_D2D_RTT;
1845 fset |= WIFI_FEATURE_D2AP_RTT;
1846 }
1847#ifdef FEATURE_WLAN_SCAN_PNO
1848 if (pHddCtx->config->configPNOScanSupport &&
1849 sme_is_feature_supported_by_fw(PNO)) {
1850 hddLog(LOG1, FL("PNO is supported by firmware"));
1851 fset |= WIFI_FEATURE_PNO;
1852 }
1853#endif
1854 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1855#ifdef FEATURE_WLAN_TDLS
1856 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1857 sme_is_feature_supported_by_fw(TDLS)) {
1858 hddLog(LOG1, FL("TDLS is supported by firmware"));
1859 fset |= WIFI_FEATURE_TDLS;
1860 }
1861 if (sme_is_feature_supported_by_fw(TDLS) &&
1862 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1863 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
1864 hddLog(LOG1, FL("TDLS off-channel is supported by firmware"));
1865 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1866 }
1867#endif
1868#ifdef WLAN_AP_STA_CONCURRENCY
1869 fset |= WIFI_FEATURE_AP_STA;
1870#endif
1871 fset |= WIFI_FEATURE_RSSI_MONITOR;
1872
1873 if (hdd_link_layer_stats_supported())
1874 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1875
1876 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1877 NLMSG_HDRLEN);
1878 if (!skb) {
1879 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1880 return -EINVAL;
1881 }
1882 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
1883 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
1884 hddLog(LOGE, FL("nla put fail"));
1885 goto nla_put_failure;
1886 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301887 ret = cfg80211_vendor_cmd_reply(skb);
1888 EXIT();
1889 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890nla_put_failure:
1891 kfree_skb(skb);
1892 return -EINVAL;
1893}
1894
1895/**
1896 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1897 * @wiphy: pointer to wireless wiphy structure.
1898 * @wdev: pointer to wireless_dev structure.
1899 * @data: Pointer to the data to be passed via vendor interface
1900 * @data_len:Length of the data to be passed
1901 *
1902 * Return: Return the Success or Failure code.
1903 */
1904static int
1905wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1906 struct wireless_dev *wdev,
1907 const void *data, int data_len)
1908{
1909 int ret = 0;
1910
1911 cds_ssr_protect(__func__);
1912 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1913 data, data_len);
1914 cds_ssr_unprotect(__func__);
1915
1916 return ret;
1917}
1918
1919/**
1920 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1921 * @wiphy: pointer to wireless wiphy structure.
1922 * @wdev: pointer to wireless_dev structure.
1923 * @data: Pointer to the data to be passed via vendor interface
1924 * @data_len:Length of the data to be passed
1925 *
1926 * Set the MAC address that is to be used for scanning.
1927 *
1928 * Return: Return the Success or Failure code.
1929 */
1930static int
1931__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1932 struct wireless_dev *wdev,
1933 const void *data,
1934 int data_len)
1935{
1936 tpSirScanMacOui pReqMsg = NULL;
1937 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1938 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301939 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 int ret;
1941
Jeff Johnson1f61b612016-02-12 16:28:33 -08001942 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943
Anurag Chouhan6d760662016-02-20 16:05:43 +05301944 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945 hdd_err("Command not allowed in FTM mode");
1946 return -EPERM;
1947 }
1948
1949 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301950 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952
1953 if (false == pHddCtx->config->enable_mac_spoofing) {
1954 hddLog(LOGW, FL("MAC address spoofing is not enabled"));
1955 return -ENOTSUPP;
1956 }
1957
1958 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1959 data, data_len, NULL)) {
1960 hddLog(LOGE, FL("Invalid ATTR"));
1961 return -EINVAL;
1962 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301963 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 if (!pReqMsg) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301965 hddLog(LOGE, FL("qdf_mem_malloc failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 return -ENOMEM;
1967 }
1968 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
1969 hddLog(LOGE, FL("attr mac oui failed"));
1970 goto fail;
1971 }
1972 nla_memcpy(&pReqMsg->oui[0],
1973 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1974 sizeof(pReqMsg->oui));
1975 hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0],
1976 pReqMsg->oui[1], pReqMsg->oui[2]);
1977 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301978 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301979 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 FL("sme_set_scanning_mac_oui failed(err=%d)"), status);
1981 goto fail;
1982 }
1983 return 0;
1984fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301985 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 return -EINVAL;
1987}
1988
1989/**
1990 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1991 * @wiphy: pointer to wireless wiphy structure.
1992 * @wdev: pointer to wireless_dev structure.
1993 * @data: Pointer to the data to be passed via vendor interface
1994 * @data_len:Length of the data to be passed
1995 *
1996 * Set the MAC address that is to be used for scanning. This is an
1997 * SSR-protecting wrapper function.
1998 *
1999 * Return: Return the Success or Failure code.
2000 */
2001static int
2002wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2003 struct wireless_dev *wdev,
2004 const void *data,
2005 int data_len)
2006{
2007 int ret;
2008
2009 cds_ssr_protect(__func__);
2010 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2011 data, data_len);
2012 cds_ssr_unprotect(__func__);
2013
2014 return ret;
2015}
2016
2017/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302018 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2019 * @wiphy: pointer phy adapter
2020 * @wdev: pointer to wireless device structure
2021 * @data: pointer to data buffer
2022 * @data_len: length of data
2023 *
2024 * This routine will give concurrency matrix
2025 *
2026 * Return: int status code
2027 */
2028static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2029 struct wireless_dev *wdev,
2030 const void *data,
2031 int data_len)
2032{
2033 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2034 uint8_t i, feature_sets, max_feature_sets;
2035 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2036 struct sk_buff *reply_skb;
2037 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2038 int ret;
2039
2040 ENTER_DEV(wdev->netdev);
2041
2042 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2043 hdd_err("Command not allowed in FTM mode");
2044 return -EPERM;
2045 }
2046
2047 ret = wlan_hdd_validate_context(hdd_ctx);
2048 if (0 != ret) {
2049 hdd_err("HDD context is not valid");
2050 return ret;
2051 }
2052
2053 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2054 data, data_len, NULL)) {
2055 hdd_err("Invalid ATTR");
2056 return -EINVAL;
2057 }
2058
2059 /* Parse and fetch max feature set */
2060 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2061 hdd_err("Attr max feature set size failed");
2062 return -EINVAL;
2063 }
2064 max_feature_sets = nla_get_u32(tb[
2065 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2066 hdd_info("Max feature set size: %d", max_feature_sets);
2067
2068 /* Fill feature combination matrix */
2069 feature_sets = 0;
2070 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2071 WIFI_FEATURE_P2P;
2072 /* Add more feature combinations here */
2073
2074 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2075 hdd_info("Number of feature sets:%d", feature_sets);
2076 hdd_info("Feature set matrix");
2077 for (i = 0; i < feature_sets; i++)
2078 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2079
2080 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2081 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2082 if (!reply_skb) {
2083 hdd_err("Feature set matrix: buffer alloc fail");
2084 return -ENOMEM;
2085 }
2086
2087 if (nla_put_u32(reply_skb,
2088 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2089 feature_sets) ||
2090 nla_put(reply_skb,
2091 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2092 sizeof(u32) * feature_sets,
2093 feature_set_matrix)) {
2094 hdd_err("nla put fail");
2095 kfree_skb(reply_skb);
2096 return -EINVAL;
2097 }
2098 return cfg80211_vendor_cmd_reply(reply_skb);
2099}
2100
2101/**
2102 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2103 * @wiphy: pointer to wireless wiphy structure.
2104 * @wdev: pointer to wireless_dev structure.
2105 * @data: Pointer to the data to be passed via vendor interface
2106 * @data_len:Length of the data to be passed
2107 *
2108 * Retrieves the concurrency feature set matrix
2109 *
2110 * Return: 0 on success, negative errno on failure
2111 */
2112static int
2113wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2114 struct wireless_dev *wdev,
2115 const void *data,
2116 int data_len)
2117{
2118 int ret;
2119
2120 cds_ssr_protect(__func__);
2121 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2122 data, data_len);
2123 cds_ssr_unprotect(__func__);
2124
2125 return ret;
2126}
2127
2128/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2130 * @feature_flags: pointer to the byte array of features.
2131 * @feature: Feature to be turned ON in the byte array.
2132 *
2133 * Return: None
2134 *
2135 * This is called to turn ON or SET the feature flag for the requested feature.
2136 **/
2137#define NUM_BITS_IN_BYTE 8
2138void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2139{
2140 uint32_t index;
2141 uint8_t bit_mask;
2142
2143 index = feature / NUM_BITS_IN_BYTE;
2144 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2145 feature_flags[index] |= bit_mask;
2146}
2147
2148/**
2149 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2150 * @wiphy: pointer to wireless wiphy structure.
2151 * @wdev: pointer to wireless_dev structure.
2152 * @data: Pointer to the data to be passed via vendor interface
2153 * @data_len:Length of the data to be passed
2154 *
2155 * This is called when wlan driver needs to send supported feature set to
2156 * supplicant upon a request/query from the supplicant.
2157 *
2158 * Return: Return the Success or Failure code.
2159 **/
2160#define MAX_CONCURRENT_CHAN_ON_24G 2
2161#define MAX_CONCURRENT_CHAN_ON_5G 2
2162static int
2163__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2164 struct wireless_dev *wdev,
2165 const void *data, int data_len)
2166{
2167 struct sk_buff *skb = NULL;
2168 uint32_t dbs_capability = 0;
2169 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302170 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 int ret_val;
2172
2173 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2174 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2175
Jeff Johnson1f61b612016-02-12 16:28:33 -08002176 ENTER_DEV(wdev->netdev);
2177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2179 if (ret_val)
2180 return ret_val;
2181
Anurag Chouhan6d760662016-02-20 16:05:43 +05302182 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 hdd_err("Command not allowed in FTM mode");
2184 return -EPERM;
2185 }
2186
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08002187 if (is_roaming_offload_enabled(hdd_ctx_ptr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188 hddLog(LOG1, FL("Key Mgmt Offload is supported"));
2189 wlan_hdd_cfg80211_set_feature(feature_flags,
2190 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2191 }
2192
2193 wlan_hdd_cfg80211_set_feature(feature_flags,
2194 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2195 if (wma_is_scan_simultaneous_capable())
2196 wlan_hdd_cfg80211_set_feature(feature_flags,
2197 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
2198 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2199 NLMSG_HDRLEN);
2200
2201 if (!skb) {
2202 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2203 return -ENOMEM;
2204 }
2205
2206 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2207 sizeof(feature_flags), feature_flags))
2208 goto nla_put_failure;
2209
2210 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302211 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 if (one_by_one_dbs)
2213 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2214
2215 if (two_by_two_dbs)
2216 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2217
2218 if (!one_by_one_dbs && !two_by_two_dbs)
2219 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2220 } else {
2221 hdd_err("wma_get_dbs_hw_mode failed");
2222 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2223 }
2224
2225 hdd_info("dbs_capability is %d", dbs_capability);
2226
2227 if (nla_put_u32(skb,
2228 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2229 MAX_CONCURRENT_CHAN_ON_24G))
2230 goto nla_put_failure;
2231
2232 if (nla_put_u32(skb,
2233 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2234 MAX_CONCURRENT_CHAN_ON_5G))
2235 goto nla_put_failure;
2236
2237 return cfg80211_vendor_cmd_reply(skb);
2238
2239nla_put_failure:
2240 kfree_skb(skb);
2241 return -EINVAL;
2242}
2243
2244/**
2245 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2246 * @wiphy: pointer to wireless wiphy structure.
2247 * @wdev: pointer to wireless_dev structure.
2248 * @data: Pointer to the data to be passed via vendor interface
2249 * @data_len:Length of the data to be passed
2250 *
2251 * This is called when wlan driver needs to send supported feature set to
2252 * supplicant upon a request/query from the supplicant.
2253 *
2254 * Return: Return the Success or Failure code.
2255 */
2256static int
2257wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2258 struct wireless_dev *wdev,
2259 const void *data, int data_len)
2260{
2261 int ret;
2262
2263 cds_ssr_protect(__func__);
2264 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2265 data, data_len);
2266 cds_ssr_unprotect(__func__);
2267
2268 return ret;
2269}
2270
2271
2272/**
2273 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2274 * @wiphy: The wiphy structure
2275 * @wdev: The wireless device
2276 * @data: Data passed by framework
2277 * @data_len: Parameters to be configured passed as data
2278 *
2279 * The roaming related parameters are configured by the framework
2280 * using this interface.
2281 *
2282 * Return: Return either success or failure code.
2283 */
2284static int
2285__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2286 struct wireless_dev *wdev, const void *data, int data_len)
2287{
2288 struct net_device *dev = wdev->netdev;
2289 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2290 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2291 uint8_t session_id;
2292 struct roam_ext_params roam_params;
2293 uint32_t cmd_type, req_id;
2294 struct nlattr *curr_attr;
2295 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2296 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2297 int rem, i;
2298 uint32_t buf_len = 0;
2299 int ret;
2300
Jeff Johnson1f61b612016-02-12 16:28:33 -08002301 ENTER_DEV(dev);
2302
Anurag Chouhan6d760662016-02-20 16:05:43 +05302303 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002304 hdd_err("Command not allowed in FTM mode");
2305 return -EPERM;
2306 }
2307
2308 ret = wlan_hdd_validate_context(pHddCtx);
2309 if (0 != ret) {
2310 hddLog(LOGE, FL("HDD context is not valid"));
2311 return -EINVAL;
2312 }
2313
2314 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2315 data, data_len,
2316 NULL)) {
2317 hddLog(LOGE, FL("Invalid ATTR"));
2318 return -EINVAL;
2319 }
2320 /* Parse and fetch Command Type*/
2321 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
2322 hddLog(LOGE, FL("roam cmd type failed"));
2323 goto fail;
2324 }
2325 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302326 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2328 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
2329 hddLog(LOGE, FL("attr request id failed"));
2330 goto fail;
2331 }
2332 req_id = nla_get_u32(
2333 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302334 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id);
2335 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 switch (cmd_type) {
2337 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2338 i = 0;
2339 nla_for_each_nested(curr_attr,
2340 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2341 rem) {
2342 if (nla_parse(tb2,
2343 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2344 nla_data(curr_attr), nla_len(curr_attr),
2345 NULL)) {
2346 hddLog(LOGE,
2347 FL("nla_parse failed"));
2348 goto fail;
2349 }
2350 /* Parse and Fetch allowed SSID list*/
2351 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
2352 hddLog(LOGE, FL("attr allowed ssid failed"));
2353 goto fail;
2354 }
2355 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2356 /*
2357 * Upper Layers include a null termination character.
2358 * Check for the actual permissible length of SSID and
2359 * also ensure not to copy the NULL termination
2360 * character to the driver buffer.
2361 */
2362 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2363 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2364 nla_memcpy(
2365 roam_params.ssid_allowed_list[i].ssId,
2366 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2367 buf_len - 1);
2368 roam_params.ssid_allowed_list[i].length =
2369 buf_len - 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302370 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 FL("SSID[%d]: %.*s,length = %d"), i,
2372 roam_params.ssid_allowed_list[i].length,
2373 roam_params.ssid_allowed_list[i].ssId,
2374 roam_params.ssid_allowed_list[i].length);
2375 i++;
2376 } else {
2377 hddLog(LOGE, FL("Invalid buffer length"));
2378 }
2379 }
2380 roam_params.num_ssid_allowed_list = i;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302381 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 roam_params.num_ssid_allowed_list);
2383 sme_update_roam_params(pHddCtx->hHal, session_id,
2384 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2385 break;
2386 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2387 /* Parse and fetch 5G Boost Threshold */
2388 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
2389 hddLog(LOGE, FL("5G boost threshold failed"));
2390 goto fail;
2391 }
2392 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2393 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302394 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 roam_params.raise_rssi_thresh_5g);
2396 /* Parse and fetch 5G Penalty Threshold */
2397 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
2398 hddLog(LOGE, FL("5G penalty threshold failed"));
2399 goto fail;
2400 }
2401 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2402 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302403 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 roam_params.drop_rssi_thresh_5g);
2405 /* Parse and fetch 5G Boost Factor */
2406 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
2407 hddLog(LOGE, FL("5G boost Factor failed"));
2408 goto fail;
2409 }
2410 roam_params.raise_factor_5g = nla_get_u32(
2411 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302412 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 roam_params.raise_factor_5g);
2414 /* Parse and fetch 5G Penalty factor */
2415 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
2416 hddLog(LOGE, FL("5G Penalty Factor failed"));
2417 goto fail;
2418 }
2419 roam_params.drop_factor_5g = nla_get_u32(
2420 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302421 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 roam_params.drop_factor_5g);
2423 /* Parse and fetch 5G Max Boost */
2424 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
2425 hddLog(LOGE, FL("5G Max Boost failed"));
2426 goto fail;
2427 }
2428 roam_params.max_raise_rssi_5g = nla_get_u32(
2429 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302430 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 roam_params.max_raise_rssi_5g);
2432 /* Parse and fetch Rssi Diff */
2433 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
2434 hddLog(LOGE, FL("Rssi Diff failed"));
2435 goto fail;
2436 }
2437 roam_params.rssi_diff = nla_get_s32(
2438 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302439 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 roam_params.rssi_diff);
2441 /* Parse and fetch Alert Rssi Threshold */
2442 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
2443 hddLog(LOGE, FL("Alert Rssi Threshold failed"));
2444 goto fail;
2445 }
2446 roam_params.alert_rssi_threshold = nla_get_u32(
2447 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302448 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Alert RSSI Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 roam_params.alert_rssi_threshold);
2450 sme_update_roam_params(pHddCtx->hHal, session_id,
2451 roam_params,
2452 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2453 break;
2454 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2455 /* Parse and fetch Activate Good Rssi Roam */
2456 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
2457 hddLog(LOGE, FL("Activate Good Rssi Roam failed"));
2458 goto fail;
2459 }
2460 roam_params.good_rssi_roam = nla_get_s32(
2461 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302462 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Activate Good Rssi Roam (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 roam_params.good_rssi_roam);
2464 sme_update_roam_params(pHddCtx->hHal, session_id,
2465 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2466 break;
2467 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2468 /* Parse and fetch number of preferred BSSID */
2469 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
2470 hddLog(LOGE, FL("attr num of preferred bssid failed"));
2471 goto fail;
2472 }
2473 roam_params.num_bssid_favored = nla_get_u32(
2474 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302475 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Preferred BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 roam_params.num_bssid_favored);
2477 i = 0;
2478 nla_for_each_nested(curr_attr,
2479 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2480 rem) {
2481 if (nla_parse(tb2,
2482 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2483 nla_data(curr_attr), nla_len(curr_attr),
2484 NULL)) {
2485 hddLog(LOGE, FL("nla_parse failed"));
2486 goto fail;
2487 }
2488 /* Parse and fetch MAC address */
2489 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
2490 hddLog(LOGE, FL("attr mac address failed"));
2491 goto fail;
2492 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002493 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302495 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002496 hdd_debug(MAC_ADDRESS_STR,
2497 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498 /* Parse and fetch preference factor*/
2499 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
2500 hddLog(LOGE, FL("BSSID Preference score failed"));
2501 goto fail;
2502 }
2503 roam_params.bssid_favored_factor[i] = nla_get_u32(
2504 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302505 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("BSSID Preference score (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 roam_params.bssid_favored_factor[i]);
2507 i++;
2508 }
2509 sme_update_roam_params(pHddCtx->hHal, session_id,
2510 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2511 break;
2512 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2513 /* Parse and fetch number of blacklist BSSID */
2514 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
2515 hddLog(LOGE, FL("attr num of blacklist bssid failed"));
2516 goto fail;
2517 }
2518 roam_params.num_bssid_avoid_list = nla_get_u32(
2519 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302520 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of blacklist BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 roam_params.num_bssid_avoid_list);
2522 i = 0;
2523 nla_for_each_nested(curr_attr,
2524 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2525 rem) {
2526 if (nla_parse(tb2,
2527 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2528 nla_data(curr_attr), nla_len(curr_attr),
2529 NULL)) {
2530 hddLog(LOGE, FL("nla_parse failed"));
2531 goto fail;
2532 }
2533 /* Parse and fetch MAC address */
2534 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
2535 hddLog(LOGE, FL("attr blacklist addr failed"));
2536 goto fail;
2537 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002538 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302540 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002541 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002543 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 i++;
2545 }
2546 sme_update_roam_params(pHddCtx->hHal, session_id,
2547 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2548 break;
2549 }
2550 return 0;
2551fail:
2552 return -EINVAL;
2553}
2554
2555/**
2556 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2557 * @wiphy: pointer to wireless wiphy structure.
2558 * @wdev: pointer to wireless_dev structure.
2559 * @data: Pointer to the data to be passed via vendor interface
2560 * @data_len:Length of the data to be passed
2561 *
2562 * Return: Return the Success or Failure code.
2563 */
2564static int
2565wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2566 struct wireless_dev *wdev,
2567 const void *data,
2568 int data_len)
2569{
2570 int ret;
2571
2572 cds_ssr_protect(__func__);
2573 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2574 data, data_len);
2575 cds_ssr_unprotect(__func__);
2576
2577 return ret;
2578}
2579
2580static const struct nla_policy
2581wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2582 +1] = {
2583 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2584};
2585
2586/**
2587 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2588 * @hdd_ctx: HDD context
2589 * @device_mode: device mode
2590 * Return: bool
2591 */
2592static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002593 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594{
2595 hdd_adapter_t *adapter;
2596 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2597 hdd_ap_ctx_t *ap_ctx;
2598 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302599 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302601 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 &adapter_node);
2603
2604 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302605 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 adapter = adapter_node->pAdapter;
2607
2608 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002609 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 ap_ctx =
2611 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2612
2613 /*
2614 * if there is SAP already running on DFS channel,
2615 * do not disable scan on dfs channels. Note that
2616 * with SAP on DFS, there cannot be conurrency on
2617 * single radio. But then we can have multiple
2618 * radios !!
2619 */
2620 if (CHANNEL_STATE_DFS ==
2621 cds_get_channel_state(
2622 ap_ctx->operatingChannel)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302623 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 FL("SAP running on DFS channel"));
2625 return true;
2626 }
2627 }
2628
2629 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002630 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631 sta_ctx =
2632 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2633
2634 /*
2635 * if STA is already connected on DFS channel,
2636 * do not disable scan on dfs channels
2637 */
2638 if (hdd_conn_is_connected(sta_ctx) &&
2639 (CHANNEL_STATE_DFS ==
2640 cds_get_channel_state(
2641 sta_ctx->conn_info.operationChannel))) {
2642 hddLog(LOGE,
2643 FL("client connected on DFS channel"));
2644 return true;
2645 }
2646 }
2647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302648 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 adapter_node,
2650 &next);
2651 adapter_node = next;
2652 }
2653
2654 return false;
2655}
2656
2657/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002658 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2659 * @hdd_ctx: HDD context within host driver
2660 * @adapter: Adapter pointer
2661 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2662 *
2663 * Loops through devices to see who is operating on DFS channels
2664 * and then disables/enables DFS channels by calling SME API.
2665 * Fails the disable request if any device is active on a DFS channel.
2666 *
2667 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002669
2670int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2671 hdd_adapter_t *adapter,
2672 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302675 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677
2678 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2679 if (no_dfs_flag) {
2680 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002681 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682
2683 if (true == status)
2684 return -EOPNOTSUPP;
2685
2686 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002687 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688
2689 if (true == status)
2690 return -EOPNOTSUPP;
2691 }
2692
2693 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2694
2695 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2696
2697 /*
2698 * call the SME API to tunnel down the new channel list
2699 * to the firmware
2700 */
2701 status = sme_handle_dfs_chan_scan(
2702 h_hal, hdd_ctx->config->enableDFSChnlScan);
2703
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302704 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 ret_val = 0;
2706
2707 /*
2708 * Clear the SME scan cache also. Note that the
2709 * clearing of scan results is independent of session;
2710 * so no need to iterate over
2711 * all sessions
2712 */
2713 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302714 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 ret_val = -EPERM;
2716 }
2717
2718 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302719 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 FL(" the DFS flag has not changed"));
2721 ret_val = 0;
2722 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002723 return ret_val;
2724}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002726/**
2727 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2728 * @wiphy: corestack handler
2729 * @wdev: wireless device
2730 * @data: data
2731 * @data_len: data length
2732 * Return: success(0) or reason code for failure
2733 */
2734static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2735 struct wireless_dev *wdev,
2736 const void *data,
2737 int data_len)
2738{
2739 struct net_device *dev = wdev->netdev;
2740 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2741 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2742 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2743 int ret_val;
2744 uint32_t no_dfs_flag = 0;
2745
Jeff Johnson1f61b612016-02-12 16:28:33 -08002746 ENTER_DEV(dev);
2747
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002748 ret_val = wlan_hdd_validate_context(hdd_ctx);
2749
2750 if (ret_val) {
2751 hdd_err("HDD context is not valid");
2752 return ret_val;
2753 }
2754
2755 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2756 data, data_len,
2757 wlan_hdd_set_no_dfs_flag_config_policy)) {
2758 hdd_err("invalid attr");
2759 return -EINVAL;
2760 }
2761
2762 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2763 hdd_err("attr dfs flag failed");
2764 return -EINVAL;
2765 }
2766
2767 no_dfs_flag = nla_get_u32(
2768 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2769
2770 hddLog(LOG1, FL(" DFS flag = %d"), no_dfs_flag);
2771
2772 if (no_dfs_flag > 1) {
2773 hddLog(LOGE, FL("invalid value of dfs flag"));
2774 return -EINVAL;
2775 }
2776
2777 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2778 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 return ret_val;
2780}
2781
2782/**
2783 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2784 *
2785 * @wiphy: wiphy device pointer
2786 * @wdev: wireless device pointer
2787 * @data: Vendof command data buffer
2788 * @data_len: Buffer length
2789 *
2790 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2791 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2792 *
2793 * Return: EOK or other error codes.
2794 */
2795
2796static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2797 struct wireless_dev *wdev,
2798 const void *data,
2799 int data_len)
2800{
2801 int ret;
2802
2803 cds_ssr_protect(__func__);
2804 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2805 data, data_len);
2806 cds_ssr_unprotect(__func__);
2807
2808 return ret;
2809}
2810
2811#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2812/**
2813 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2814 * @wiphy: pointer to wireless wiphy structure.
2815 * @wdev: pointer to wireless_dev structure.
2816 * @data: Pointer to the Key data
2817 * @data_len:Length of the data passed
2818 *
2819 * This is called when wlan driver needs to save the keys received via
2820 * vendor specific command.
2821 *
2822 * Return: Return the Success or Failure code.
2823 */
2824static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2825 struct wireless_dev *wdev,
2826 const void *data, int data_len)
2827{
2828 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
2829 struct net_device *dev = wdev->netdev;
2830 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
2831 hdd_context_t *hdd_ctx_ptr;
2832 int status;
2833
Jeff Johnson1f61b612016-02-12 16:28:33 -08002834 ENTER_DEV(dev);
2835
Anurag Chouhan6d760662016-02-20 16:05:43 +05302836 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002837 hdd_err("Command not allowed in FTM mode");
2838 return -EPERM;
2839 }
2840
2841 if ((data == NULL) || (data_len == 0) ||
2842 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
2843 hddLog(LOGE, FL("Invalid data"));
2844 return -EINVAL;
2845 }
2846
2847 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
2848 if (!hdd_ctx_ptr) {
2849 hddLog(LOGE, FL("HDD context is null"));
2850 return -EINVAL;
2851 }
2852
2853 status = wlan_hdd_validate_context(hdd_ctx_ptr);
2854 if (0 != status) {
2855 hddLog(LOGE, FL("HDD context is invalid"));
2856 return status;
2857 }
2858 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
2859 hdd_adapter_ptr->sessionId,
2860 true);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302861 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
2862 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
2864 hdd_adapter_ptr->sessionId, local_pmk, data_len);
2865 return 0;
2866}
2867
2868/**
2869 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2870 * @wiphy: pointer to wireless wiphy structure.
2871 * @wdev: pointer to wireless_dev structure.
2872 * @data: Pointer to the Key data
2873 * @data_len:Length of the data passed
2874 *
2875 * This is called when wlan driver needs to save the keys received via
2876 * vendor specific command.
2877 *
2878 * Return: Return the Success or Failure code.
2879 */
2880static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2881 struct wireless_dev *wdev,
2882 const void *data, int data_len)
2883{
2884 int ret;
2885
2886 cds_ssr_protect(__func__);
2887 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
2888 cds_ssr_unprotect(__func__);
2889
2890 return ret;
2891}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08002892#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893
2894static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
2895 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
2896 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
2897 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
2898};
2899
2900/**
2901 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2902 * @wiphy: pointer to wireless wiphy structure.
2903 * @wdev: pointer to wireless_dev structure.
2904 * @data: Pointer to the data to be passed via vendor interface
2905 * @data_len:Length of the data to be passed
2906 *
2907 * This is called when wlan driver needs to send wifi driver related info
2908 * (driver/fw version) to the user space application upon request.
2909 *
2910 * Return: Return the Success or Failure code.
2911 */
2912static int
2913__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2914 struct wireless_dev *wdev,
2915 const void *data, int data_len)
2916{
2917 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2918 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
2919 tSirVersionString version;
2920 uint32_t version_len;
2921 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
2922 uint8_t attr;
2923 int status;
2924 struct sk_buff *reply_skb = NULL;
2925
Jeff Johnson1f61b612016-02-12 16:28:33 -08002926 ENTER_DEV(wdev->netdev);
2927
Anurag Chouhan6d760662016-02-20 16:05:43 +05302928 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 hdd_err("Command not allowed in FTM mode");
2930 return -EPERM;
2931 }
2932
2933 status = wlan_hdd_validate_context(hdd_ctx);
2934 if (0 != status) {
2935 hddLog(LOGE, FL("HDD context is not valid"));
2936 return -EINVAL;
2937 }
2938
2939 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
2940 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
2941 hddLog(LOGE, FL("WIFI_INFO_GET NL CMD parsing failed"));
2942 return -EINVAL;
2943 }
2944
2945 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
2946 hddLog(LOG1, FL("Rcvd req for Driver version"));
2947 strlcpy(version, QWLAN_VERSIONSTR, sizeof(version));
2948 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
2949 } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
2950 hddLog(LOG1, FL("Rcvd req for FW version"));
2951 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
2952 &crmid);
2953 snprintf(version, sizeof(version), "%d:%d:%d:%d",
2954 major_spid, minor_spid, siid, crmid);
2955 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
2956 } else {
2957 hddLog(LOGE, FL("Invalid attribute in get wifi info request"));
2958 return -EINVAL;
2959 }
2960
2961 version_len = strlen(version);
2962 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2963 version_len + NLA_HDRLEN + NLMSG_HDRLEN);
2964 if (!reply_skb) {
2965 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2966 return -ENOMEM;
2967 }
2968
2969 if (nla_put(reply_skb, attr, version_len, version)) {
2970 hddLog(LOGE, FL("nla put fail"));
2971 kfree_skb(reply_skb);
2972 return -EINVAL;
2973 }
2974
2975 return cfg80211_vendor_cmd_reply(reply_skb);
2976}
2977
2978/**
2979 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2980 * @wiphy: pointer to wireless wiphy structure.
2981 * @wdev: pointer to wireless_dev structure.
2982 * @data: Pointer to the data to be passed via vendor interface
2983 * @data_len:Length of the data to be passed
2984 *
2985 * This is called when wlan driver needs to send wifi driver related info
2986 * (driver/fw version) to the user space application upon request.
2987 *
2988 * Return: Return the Success or Failure code.
2989 */
2990static int
2991wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2992 struct wireless_dev *wdev,
2993 const void *data, int data_len)
2994{
2995 int ret;
2996
2997 cds_ssr_protect(__func__);
2998 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
2999 cds_ssr_unprotect(__func__);
3000
3001 return ret;
3002}
3003
3004/**
3005 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3006 * @wiphy: pointer to wireless wiphy structure.
3007 * @wdev: pointer to wireless_dev structure.
3008 * @data: Pointer to the data to be passed via vendor interface
3009 * @data_len:Length of the data to be passed
3010 *
3011 * This is called by userspace to know the supported logger features
3012 *
3013 * Return: Return the Success or Failure code.
3014 */
3015static int
3016__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3017 struct wireless_dev *wdev,
3018 const void *data, int data_len)
3019{
3020 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3021 int status;
3022 uint32_t features;
3023 struct sk_buff *reply_skb = NULL;
3024
Jeff Johnson1f61b612016-02-12 16:28:33 -08003025 ENTER_DEV(wdev->netdev);
3026
Anurag Chouhan6d760662016-02-20 16:05:43 +05303027 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 hdd_err("Command not allowed in FTM mode");
3029 return -EPERM;
3030 }
3031
3032 status = wlan_hdd_validate_context(hdd_ctx);
3033 if (0 != status) {
3034 hddLog(LOGE, FL("HDD context is not valid"));
3035 return -EINVAL;
3036 }
3037
3038 features = 0;
3039
3040 if (hdd_is_memdump_supported())
3041 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3042 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3043 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3044 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3045
3046 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3047 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3048 if (!reply_skb) {
3049 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3050 return -ENOMEM;
3051 }
3052
3053 hddLog(LOG1, FL("Supported logger features: 0x%0x"), features);
3054 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3055 features)) {
3056 hddLog(LOGE, FL("nla put fail"));
3057 kfree_skb(reply_skb);
3058 return -EINVAL;
3059 }
3060
3061 return cfg80211_vendor_cmd_reply(reply_skb);
3062}
3063
3064/**
3065 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3066 * @wiphy: pointer to wireless wiphy structure.
3067 * @wdev: pointer to wireless_dev structure.
3068 * @data: Pointer to the data to be passed via vendor interface
3069 * @data_len:Length of the data to be passed
3070 *
3071 * This is called by userspace to know the supported logger features
3072 *
3073 * Return: Return the Success or Failure code.
3074 */
3075static int
3076wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3077 struct wireless_dev *wdev,
3078 const void *data, int data_len)
3079{
3080 int ret;
3081
3082 cds_ssr_protect(__func__);
3083 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3084 data, data_len);
3085 cds_ssr_unprotect(__func__);
3086
3087 return ret;
3088}
3089
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003090#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003091/**
3092 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3093 * @hdd_ctx_ptr: pointer to HDD Context.
3094 * @bssid: pointer to bssid of roamed AP.
3095 * @req_rsn_ie: Pointer to request RSN IE
3096 * @req_rsn_len: Length of the request RSN IE
3097 * @rsp_rsn_ie: Pointer to response RSN IE
3098 * @rsp_rsn_len: Length of the response RSN IE
3099 * @roam_info_ptr: Pointer to the roaming related information
3100 *
3101 * This is called when wlan driver needs to send the roaming and
3102 * authorization information after roaming.
3103 *
3104 * The information that would be sent is the request RSN IE, response
3105 * RSN IE and BSSID of the newly roamed AP.
3106 *
3107 * If the Authorized status is authenticated, then additional parameters
3108 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3109 * supplicant.
3110 *
3111 * The supplicant upon receiving this event would ignore the legacy
3112 * cfg80211_roamed call and use the entire information from this event.
3113 * The cfg80211_roamed should still co-exist since the kernel will
3114 * make use of the parameters even if the supplicant ignores it.
3115 *
3116 * Return: Return the Success or Failure code.
3117 */
3118int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3119 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3120 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3121{
3122 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003123 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 ENTER();
3125
3126 if (wlan_hdd_validate_context(hdd_ctx_ptr)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303127 hddLog(QDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid "));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 return -EINVAL;
3129 }
3130
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003131 if (!is_roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003132 !roam_info_ptr->roamSynchInProgress)
3133 return 0;
3134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3136 NULL,
3137 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3138 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3139 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003140 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3142 GFP_KERNEL);
3143
3144 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303145 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 FL("cfg80211_vendor_event_alloc failed"));
3147 return -EINVAL;
3148 }
3149
3150 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3151 ETH_ALEN, bssid) ||
3152 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3153 req_rsn_len, req_rsn_ie) ||
3154 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3155 rsp_rsn_len, rsp_rsn_ie)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303156 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157 goto nla_put_failure;
3158 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303159 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 roam_info_ptr->synchAuthStatus);
3161 if (roam_info_ptr->synchAuthStatus ==
3162 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303163 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's"));
Naveen Rawat14298b92015-11-25 16:27:41 -08003164 if (nla_put_u8(skb,
3165 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3166 hdd_err("nla put fail");
3167 goto nla_put_failure;
3168 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003169 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3170 /* if FT or CCKM connection: dont send replay counter */
3171 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3172 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3173 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3174 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3175 nla_put(skb,
3176 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3177 SIR_REPLAY_CTR_LEN,
3178 roam_info_ptr->replay_ctr)) {
3179 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003180 hdd_err("failed to send replay counter.");
3181 goto nla_put_failure;
3182 }
3183 if (nla_put(skb,
3184 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3185 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3186 nla_put(skb,
3187 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3188 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3189 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 goto nla_put_failure;
3191 }
3192 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303193 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3195 false)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303196 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 goto nla_put_failure;
3198 }
3199 }
3200
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303201 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Subnet Change Status = %d"),
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003202 roam_info_ptr->subnet_change_status);
3203
3204 /*
3205 * Add subnet change status if subnet has changed
3206 * 0 = unchanged
3207 * 1 = changed
3208 * 2 = unknown
3209 */
3210 if (roam_info_ptr->subnet_change_status) {
3211 if (nla_put_u8(skb,
3212 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3213 roam_info_ptr->subnet_change_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303214 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003215 goto nla_put_failure;
3216 }
3217 }
3218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219 cfg80211_vendor_event(skb, GFP_KERNEL);
3220 return 0;
3221
3222nla_put_failure:
3223 kfree_skb(skb);
3224 return -EINVAL;
3225}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003226#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227
3228static const struct nla_policy
3229wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3230
3231 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3232 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3233 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3234};
3235
3236
3237/**
3238 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3239 * vendor command
3240 *
3241 * @wiphy: wiphy device pointer
3242 * @wdev: wireless device pointer
3243 * @data: Vendor command data buffer
3244 * @data_len: Buffer length
3245 *
3246 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3247 *
3248 * Return: Error code.
3249 */
3250static int
3251__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3252 struct wireless_dev *wdev,
3253 const void *data,
3254 int data_len)
3255{
3256 struct net_device *dev = wdev->netdev;
3257 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3258 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3259 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3260 int ret_val = 0;
3261 u32 modulated_dtim;
3262 u16 stats_avg_factor;
3263 u32 guard_time;
Krunal Sonie3531942016-04-12 17:43:53 -07003264 u32 ftm_capab;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303265 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266
Jeff Johnson1f61b612016-02-12 16:28:33 -08003267 ENTER_DEV(dev);
3268
Anurag Chouhan6d760662016-02-20 16:05:43 +05303269 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003270 hdd_err("Command not allowed in FTM mode");
3271 return -EPERM;
3272 }
3273
3274 ret_val = wlan_hdd_validate_context(hdd_ctx);
3275 if (ret_val) {
3276 hddLog(LOGE, FL("HDD context is not valid"));
3277 return ret_val;
3278 }
3279
3280 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3281 data, data_len,
3282 wlan_hdd_wifi_config_policy)) {
3283 hddLog(LOGE, FL("invalid attr"));
3284 return -EINVAL;
3285 }
3286
Krunal Sonie3531942016-04-12 17:43:53 -07003287 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3288 ftm_capab = nla_get_u32(tb[
3289 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3290 hdd_ctx->config->fine_time_meas_cap =
3291 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3292 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
3293 hdd_ctx->config->fine_time_meas_cap);
3294 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3295 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3296 hdd_ctx->config->fine_time_meas_cap);
3297 }
3298
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3300 modulated_dtim = nla_get_u32(
3301 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3302
3303 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3304 adapter->sessionId,
3305 modulated_dtim);
3306
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303307 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003308 ret_val = -EPERM;
3309 }
3310
3311 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3312 stats_avg_factor = nla_get_u16(
3313 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3314 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3315 adapter->sessionId,
3316 stats_avg_factor);
3317
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303318 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003319 ret_val = -EPERM;
3320 }
3321
3322
3323 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3324 guard_time = nla_get_u32(
3325 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3326 status = sme_configure_guard_time(hdd_ctx->hHal,
3327 adapter->sessionId,
3328 guard_time);
3329
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303330 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 ret_val = -EPERM;
3332 }
3333
3334 return ret_val;
3335}
3336
3337/**
3338 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3339 * vendor command
3340 *
3341 * @wiphy: wiphy device pointer
3342 * @wdev: wireless device pointer
3343 * @data: Vendor command data buffer
3344 * @data_len: Buffer length
3345 *
3346 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3347 *
3348 * Return: EOK or other error codes.
3349 */
3350static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3351 struct wireless_dev *wdev,
3352 const void *data,
3353 int data_len)
3354{
3355 int ret;
3356
3357 cds_ssr_protect(__func__);
3358 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3359 data, data_len);
3360 cds_ssr_unprotect(__func__);
3361
3362 return ret;
3363}
3364
3365static const struct
3366nla_policy
3367qca_wlan_vendor_wifi_logger_start_policy
3368[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3369 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3370 = {.type = NLA_U32 },
3371 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3372 = {.type = NLA_U32 },
3373 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3374 = {.type = NLA_U32 },
3375};
3376
3377/**
3378 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3379 * or disable the collection of packet statistics from the firmware
3380 * @wiphy: WIPHY structure pointer
3381 * @wdev: Wireless device structure pointer
3382 * @data: Pointer to the data received
3383 * @data_len: Length of the data received
3384 *
3385 * This function enables or disables the collection of packet statistics from
3386 * the firmware
3387 *
3388 * Return: 0 on success and errno on failure
3389 */
3390static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3391 struct wireless_dev *wdev,
3392 const void *data,
3393 int data_len)
3394{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303395 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3397 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
3398 struct sir_wifi_start_log start_log;
3399
Jeff Johnson1f61b612016-02-12 16:28:33 -08003400 ENTER_DEV(wdev->netdev);
3401
Anurag Chouhan6d760662016-02-20 16:05:43 +05303402 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403 hdd_err("Command not allowed in FTM mode");
3404 return -EPERM;
3405 }
3406
3407 status = wlan_hdd_validate_context(hdd_ctx);
3408 if (0 != status) {
3409 hddLog(LOGE, FL("HDD context is not valid"));
3410 return -EINVAL;
3411 }
3412
3413 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
3414 data, data_len,
3415 qca_wlan_vendor_wifi_logger_start_policy)) {
3416 hddLog(LOGE, FL("Invalid attribute"));
3417 return -EINVAL;
3418 }
3419
3420 /* Parse and fetch ring id */
3421 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
3422 hddLog(LOGE, FL("attr ATTR failed"));
3423 return -EINVAL;
3424 }
3425 start_log.ring_id = nla_get_u32(
3426 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003427 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428
3429 /* Parse and fetch verbose level */
3430 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
3431 hddLog(LOGE, FL("attr verbose_level failed"));
3432 return -EINVAL;
3433 }
3434 start_log.verbose_level = nla_get_u32(
3435 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003436 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003437
3438 /* Parse and fetch flag */
3439 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
3440 hddLog(LOGE, FL("attr flag failed"));
3441 return -EINVAL;
3442 }
3443 start_log.flag = nla_get_u32(
3444 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003445 hdd_info("flag=%d", start_log.flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003446
3447 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
3448
3449 if (start_log.ring_id == RING_ID_WAKELOCK) {
3450 /* Start/stop wakelock events */
3451 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
3452 cds_set_wakelock_logging(true);
3453 else
3454 cds_set_wakelock_logging(false);
3455 return 0;
3456 }
3457
3458 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303459 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003460 hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"),
3461 status);
3462 return -EINVAL;
3463 }
3464 return 0;
3465}
3466
3467/**
3468 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
3469 * or disable the collection of packet statistics from the firmware
3470 * @wiphy: WIPHY structure pointer
3471 * @wdev: Wireless device structure pointer
3472 * @data: Pointer to the data received
3473 * @data_len: Length of the data received
3474 *
3475 * This function is used to enable or disable the collection of packet
3476 * statistics from the firmware
3477 *
3478 * Return: 0 on success and errno on failure
3479 */
3480static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3481 struct wireless_dev *wdev,
3482 const void *data,
3483 int data_len)
3484{
3485 int ret = 0;
3486
3487 cds_ssr_protect(__func__);
3488 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
3489 wdev, data, data_len);
3490 cds_ssr_unprotect(__func__);
3491
3492 return ret;
3493}
3494
3495static const struct
3496nla_policy
3497qca_wlan_vendor_wifi_logger_get_ring_data_policy
3498[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
3499 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
3500 = {.type = NLA_U32 },
3501};
3502
3503/**
3504 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
3505 * @wiphy: WIPHY structure pointer
3506 * @wdev: Wireless device structure pointer
3507 * @data: Pointer to the data received
3508 * @data_len: Length of the data received
3509 *
3510 * This function is used to flush or retrieve the per packet statistics from
3511 * the driver
3512 *
3513 * Return: 0 on success and errno on failure
3514 */
3515static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3516 struct wireless_dev *wdev,
3517 const void *data,
3518 int data_len)
3519{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303520 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003521 uint32_t ring_id;
3522 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3523 struct nlattr *tb
3524 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
3525
Jeff Johnson1f61b612016-02-12 16:28:33 -08003526 ENTER_DEV(wdev->netdev);
3527
Anurag Chouhan6d760662016-02-20 16:05:43 +05303528 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003529 hdd_err("Command not allowed in FTM mode");
3530 return -EPERM;
3531 }
3532
3533 status = wlan_hdd_validate_context(hdd_ctx);
3534 if (0 != status) {
3535 hddLog(LOGE, FL("HDD context is not valid"));
3536 return -EINVAL;
3537 }
3538
3539 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
3540 data, data_len,
3541 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
3542 hddLog(LOGE, FL("Invalid attribute"));
3543 return -EINVAL;
3544 }
3545
3546 /* Parse and fetch ring id */
3547 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
3548 hddLog(LOGE, FL("attr ATTR failed"));
3549 return -EINVAL;
3550 }
3551
3552 ring_id = nla_get_u32(
3553 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
3554
3555 if (ring_id == RING_ID_PER_PACKET_STATS) {
3556 wlan_logging_set_per_pkt_stats();
3557 hddLog(LOG1, FL("Flushing/Retrieving packet stats"));
3558 }
3559
3560 hddLog(LOG1, FL("Bug report triggered by framework"));
3561
3562 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
3563 WLAN_LOG_INDICATOR_FRAMEWORK,
3564 WLAN_LOG_REASON_CODE_UNUSED);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303565 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 hddLog(LOGE, FL("Failed to trigger bug report"));
3567 return -EINVAL;
3568 }
3569
3570 return 0;
3571}
3572
3573/**
3574 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
3575 * @wiphy: WIPHY structure pointer
3576 * @wdev: Wireless device structure pointer
3577 * @data: Pointer to the data received
3578 * @data_len: Length of the data received
3579 *
3580 * This function is used to flush or retrieve the per packet statistics from
3581 * the driver
3582 *
3583 * Return: 0 on success and errno on failure
3584 */
3585static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3586 struct wireless_dev *wdev,
3587 const void *data,
3588 int data_len)
3589{
3590 int ret = 0;
3591
3592 cds_ssr_protect(__func__);
3593 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
3594 wdev, data, data_len);
3595 cds_ssr_unprotect(__func__);
3596
3597 return ret;
3598}
3599
3600#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
3601/**
3602 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
3603 * @hdd_ctx: HDD context
3604 * @request_id: [input] request id
3605 * @pattern_id: [output] pattern id
3606 *
3607 * This function loops through request id to pattern id array
3608 * if the slot is available, store the request id and return pattern id
3609 * if entry exists, return the pattern id
3610 *
3611 * Return: 0 on success and errno on failure
3612 */
3613static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3614 uint32_t request_id,
3615 uint8_t *pattern_id)
3616{
3617 uint32_t i;
3618
3619 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3620 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3621 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
3622 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
3623 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3624 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3625 return 0;
3626 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
3627 request_id) {
3628 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3629 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3630 return 0;
3631 }
3632 }
3633 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3634 return -EINVAL;
3635}
3636
3637/**
3638 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
3639 * @hdd_ctx: HDD context
3640 * @request_id: [input] request id
3641 * @pattern_id: [output] pattern id
3642 *
3643 * This function loops through request id to pattern id array
3644 * reset request id to 0 (slot available again) and
3645 * return pattern id
3646 *
3647 * Return: 0 on success and errno on failure
3648 */
3649static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3650 uint32_t request_id,
3651 uint8_t *pattern_id)
3652{
3653 uint32_t i;
3654
3655 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3656 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3657 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
3658 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
3659 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3660 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3661 return 0;
3662 }
3663 }
3664 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3665 return -EINVAL;
3666}
3667
3668
3669/*
3670 * define short names for the global vendor params
3671 * used by __wlan_hdd_cfg80211_offloaded_packets()
3672 */
3673#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
3674#define PARAM_REQUEST_ID \
3675 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
3676#define PARAM_CONTROL \
3677 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
3678#define PARAM_IP_PACKET \
3679 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
3680#define PARAM_SRC_MAC_ADDR \
3681 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
3682#define PARAM_DST_MAC_ADDR \
3683 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
3684#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
3685
3686/**
3687 * wlan_hdd_add_tx_ptrn() - add tx pattern
3688 * @adapter: adapter pointer
3689 * @hdd_ctx: hdd context
3690 * @tb: nl attributes
3691 *
3692 * This function reads the NL attributes and forms a AddTxPtrn message
3693 * posts it to SME.
3694 *
3695 */
3696static int
3697wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3698 struct nlattr **tb)
3699{
3700 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303701 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 uint32_t request_id, ret, len;
3703 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303704 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705 uint16_t eth_type = htons(ETH_P_IP);
3706
3707 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3708 hddLog(LOGE, FL("Not in Connected state!"));
3709 return -ENOTSUPP;
3710 }
3711
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303712 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 if (!add_req) {
3714 hddLog(LOGE, FL("memory allocation failed"));
3715 return -ENOMEM;
3716 }
3717
3718 /* Parse and fetch request Id */
3719 if (!tb[PARAM_REQUEST_ID]) {
3720 hddLog(LOGE, FL("attr request id failed"));
3721 goto fail;
3722 }
3723
3724 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3725 if (request_id == MAX_REQUEST_ID) {
3726 hddLog(LOGE, FL("request_id cannot be MAX"));
3727 return -EINVAL;
3728 }
3729 hddLog(LOG1, FL("Request Id: %u"), request_id);
3730
3731 if (!tb[PARAM_PERIOD]) {
3732 hddLog(LOGE, FL("attr period failed"));
3733 goto fail;
3734 }
3735 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
3736 hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs);
3737 if (add_req->usPtrnIntervalMs == 0) {
3738 hddLog(LOGE, FL("Invalid interval zero, return failure"));
3739 goto fail;
3740 }
3741
3742 if (!tb[PARAM_SRC_MAC_ADDR]) {
3743 hddLog(LOGE, FL("attr source mac address failed"));
3744 goto fail;
3745 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08003746 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303747 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748 hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003749 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750
Anurag Chouhanc5548422016-02-24 18:33:27 +05303751 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003752 &adapter->macAddressCurrent)) {
3753 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003754 goto fail;
3755 }
3756
3757 if (!tb[PARAM_DST_MAC_ADDR]) {
3758 hddLog(LOGE, FL("attr dst mac address failed"));
3759 goto fail;
3760 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303761 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762 hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR,
3763 MAC_ADDR_ARRAY(dst_addr.bytes));
3764
3765 if (!tb[PARAM_IP_PACKET]) {
3766 hddLog(LOGE, FL("attr ip packet failed"));
3767 goto fail;
3768 }
3769 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
3770 hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize);
3771
3772 if (add_req->ucPtrnSize < 0 ||
3773 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
3774 ETH_HLEN)) {
3775 hddLog(LOGE, FL("Invalid IP packet len: %d"),
3776 add_req->ucPtrnSize);
3777 goto fail;
3778 }
3779
3780 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303781 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303782 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303783 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303784 QDF_MAC_ADDR_SIZE);
3785 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303786 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 len += 2;
3788
3789 /*
3790 * This is the IP packet, add 14 bytes Ethernet (802.3) header
3791 * ------------------------------------------------------------
3792 * | 14 bytes Ethernet (802.3) header | IP header and payload |
3793 * ------------------------------------------------------------
3794 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303795 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796 nla_data(tb[PARAM_IP_PACKET]),
3797 add_req->ucPtrnSize);
3798 add_req->ucPtrnSize += len;
3799
3800 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3801 if (ret) {
3802 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3803 goto fail;
3804 }
3805 add_req->ucPtrnId = pattern_id;
3806 hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId);
3807
3808 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303809 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 hddLog(LOGE,
3811 FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status);
3812 goto fail;
3813 }
3814
3815 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303816 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 return 0;
3818
3819fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303820 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821 return -EINVAL;
3822}
3823
3824/**
3825 * wlan_hdd_del_tx_ptrn() - delete tx pattern
3826 * @adapter: adapter pointer
3827 * @hdd_ctx: hdd context
3828 * @tb: nl attributes
3829 *
3830 * This function reads the NL attributes and forms a DelTxPtrn message
3831 * posts it to SME.
3832 *
3833 */
3834static int
3835wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3836 struct nlattr **tb)
3837{
3838 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303839 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 uint32_t request_id, ret;
3841 uint8_t pattern_id = 0;
3842
3843 /* Parse and fetch request Id */
3844 if (!tb[PARAM_REQUEST_ID]) {
3845 hddLog(LOGE, FL("attr request id failed"));
3846 return -EINVAL;
3847 }
3848 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3849 if (request_id == MAX_REQUEST_ID) {
3850 hddLog(LOGE, FL("request_id cannot be MAX"));
3851 return -EINVAL;
3852 }
3853
3854 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3855 if (ret) {
3856 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3857 return -EINVAL;
3858 }
3859
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303860 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003861 if (!del_req) {
3862 hddLog(LOGE, FL("memory allocation failed"));
3863 return -ENOMEM;
3864 }
3865
Anurag Chouhanc5548422016-02-24 18:33:27 +05303866 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08003867 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868 del_req->ucPtrnId = pattern_id;
3869 hddLog(LOG1, FL("Request Id: %u Pattern id: %d"),
3870 request_id, del_req->ucPtrnId);
3871
3872 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303873 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 hddLog(LOGE,
3875 FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status);
3876 goto fail;
3877 }
3878
3879 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303880 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881 return 0;
3882
3883fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303884 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 return -EINVAL;
3886}
3887
3888
3889/**
3890 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
3891 * @wiphy: Pointer to wireless phy
3892 * @wdev: Pointer to wireless device
3893 * @data: Pointer to data
3894 * @data_len: Data length
3895 *
3896 * Return: 0 on success, negative errno on failure
3897 */
3898static int
3899__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3900 struct wireless_dev *wdev,
3901 const void *data,
3902 int data_len)
3903{
3904 struct net_device *dev = wdev->netdev;
3905 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3906 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3907 struct nlattr *tb[PARAM_MAX + 1];
3908 uint8_t control;
3909 int ret;
3910 static const struct nla_policy policy[PARAM_MAX + 1] = {
3911 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3912 [PARAM_CONTROL] = { .type = NLA_U32 },
3913 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303914 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303916 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 [PARAM_PERIOD] = { .type = NLA_U32 },
3918 };
3919
Jeff Johnson1f61b612016-02-12 16:28:33 -08003920 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921
Anurag Chouhan6d760662016-02-20 16:05:43 +05303922 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003923 hdd_err("Command not allowed in FTM mode");
3924 return -EPERM;
3925 }
3926
3927 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303928 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930
3931 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
3932 hddLog(LOGE,
3933 FL("Periodic Tx Pattern Offload feature is not supported in FW!"));
3934 return -ENOTSUPP;
3935 }
3936
3937 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3938 hddLog(LOGE, FL("Invalid ATTR"));
3939 return -EINVAL;
3940 }
3941
3942 if (!tb[PARAM_CONTROL]) {
3943 hddLog(LOGE, FL("attr control failed"));
3944 return -EINVAL;
3945 }
3946 control = nla_get_u32(tb[PARAM_CONTROL]);
3947 hddLog(LOG1, FL("Control: %d"), control);
3948
3949 if (control == WLAN_START_OFFLOADED_PACKETS)
3950 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
3951 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
3952 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
3953 else {
3954 hddLog(LOGE, FL("Invalid control: %d"), control);
3955 return -EINVAL;
3956 }
3957}
3958
3959/*
3960 * done with short names for the global vendor params
3961 * used by __wlan_hdd_cfg80211_offloaded_packets()
3962 */
3963#undef PARAM_MAX
3964#undef PARAM_REQUEST_ID
3965#undef PARAM_CONTROL
3966#undef PARAM_IP_PACKET
3967#undef PARAM_SRC_MAC_ADDR
3968#undef PARAM_DST_MAC_ADDR
3969#undef PARAM_PERIOD
3970
3971/**
3972 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
3973 * @wiphy: wiphy structure pointer
3974 * @wdev: Wireless device structure pointer
3975 * @data: Pointer to the data received
3976 * @data_len: Length of @data
3977 *
3978 * Return: 0 on success; errno on failure
3979 */
3980static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3981 struct wireless_dev *wdev,
3982 const void *data,
3983 int data_len)
3984{
3985 int ret = 0;
3986
3987 cds_ssr_protect(__func__);
3988 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
3989 wdev, data, data_len);
3990 cds_ssr_unprotect(__func__);
3991
3992 return ret;
3993}
3994#endif
3995
3996/*
3997 * define short names for the global vendor params
3998 * used by __wlan_hdd_cfg80211_monitor_rssi()
3999 */
4000#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4001#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4002#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4003#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4004#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4005
4006/**
4007 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4008 * @wiphy: Pointer to wireless phy
4009 * @wdev: Pointer to wireless device
4010 * @data: Pointer to data
4011 * @data_len: Data length
4012 *
4013 * Return: 0 on success, negative errno on failure
4014 */
4015static int
4016__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4017 struct wireless_dev *wdev,
4018 const void *data,
4019 int data_len)
4020{
4021 struct net_device *dev = wdev->netdev;
4022 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4023 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4024 struct nlattr *tb[PARAM_MAX + 1];
4025 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304026 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004027 int ret;
4028 uint32_t control;
4029 static const struct nla_policy policy[PARAM_MAX + 1] = {
4030 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4031 [PARAM_CONTROL] = { .type = NLA_U32 },
4032 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4033 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4034 };
4035
Jeff Johnson1f61b612016-02-12 16:28:33 -08004036 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037
4038 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304039 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041
4042 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
4043 hddLog(LOGE, FL("Not in Connected state!"));
4044 return -ENOTSUPP;
4045 }
4046
4047 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
4048 hddLog(LOGE, FL("Invalid ATTR"));
4049 return -EINVAL;
4050 }
4051
4052 if (!tb[PARAM_REQUEST_ID]) {
4053 hddLog(LOGE, FL("attr request id failed"));
4054 return -EINVAL;
4055 }
4056
4057 if (!tb[PARAM_CONTROL]) {
4058 hddLog(LOGE, FL("attr control failed"));
4059 return -EINVAL;
4060 }
4061
4062 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4063 req.session_id = adapter->sessionId;
4064 control = nla_get_u32(tb[PARAM_CONTROL]);
4065
4066 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4067 req.control = true;
4068 if (!tb[PARAM_MIN_RSSI]) {
4069 hddLog(LOGE, FL("attr min rssi failed"));
4070 return -EINVAL;
4071 }
4072
4073 if (!tb[PARAM_MAX_RSSI]) {
4074 hddLog(LOGE, FL("attr max rssi failed"));
4075 return -EINVAL;
4076 }
4077
4078 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4079 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4080
4081 if (!(req.min_rssi < req.max_rssi)) {
4082 hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"),
4083 req.min_rssi, req.max_rssi);
4084 return -EINVAL;
4085 }
4086 hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"),
4087 req.min_rssi, req.max_rssi);
4088
4089 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4090 req.control = false;
4091 else {
4092 hddLog(LOGE, FL("Invalid control cmd: %d"), control);
4093 return -EINVAL;
4094 }
4095 hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"),
4096 req.request_id, req.session_id, req.control);
4097
4098 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304099 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100 hddLog(LOGE,
4101 FL("sme_set_rssi_monitoring failed(err=%d)"), status);
4102 return -EINVAL;
4103 }
4104
4105 return 0;
4106}
4107
4108/*
4109 * done with short names for the global vendor params
4110 * used by __wlan_hdd_cfg80211_monitor_rssi()
4111 */
4112#undef PARAM_MAX
4113#undef PARAM_CONTROL
4114#undef PARAM_REQUEST_ID
4115#undef PARAM_MAX_RSSI
4116#undef PARAM_MIN_RSSI
4117
4118/**
4119 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4120 * @wiphy: wiphy structure pointer
4121 * @wdev: Wireless device structure pointer
4122 * @data: Pointer to the data received
4123 * @data_len: Length of @data
4124 *
4125 * Return: 0 on success; errno on failure
4126 */
4127static int
4128wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4129 const void *data, int data_len)
4130{
4131 int ret;
4132
4133 cds_ssr_protect(__func__);
4134 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4135 cds_ssr_unprotect(__func__);
4136
4137 return ret;
4138}
4139
4140/**
4141 * hdd_rssi_threshold_breached() - rssi breached NL event
4142 * @hddctx: HDD context
4143 * @data: rssi breached event data
4144 *
4145 * This function reads the rssi breached event %data and fill in the skb with
4146 * NL attributes and send up the NL event.
4147 *
4148 * Return: none
4149 */
4150void hdd_rssi_threshold_breached(void *hddctx,
4151 struct rssi_breach_event *data)
4152{
4153 hdd_context_t *hdd_ctx = hddctx;
4154 struct sk_buff *skb;
4155
4156 ENTER();
4157
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304158 if (wlan_hdd_validate_context(hdd_ctx))
4159 return;
4160 if (!data) {
4161 hddLog(LOGE, FL("data is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162 return;
4163 }
4164
4165 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4166 NULL,
4167 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4168 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4169 GFP_KERNEL);
4170
4171 if (!skb) {
4172 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
4173 return;
4174 }
4175
4176 hddLog(LOG1, "Req Id: %u Current rssi: %d",
4177 data->request_id, data->curr_rssi);
4178 hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR,
4179 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4180
4181 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4182 data->request_id) ||
4183 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4184 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4185 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4186 data->curr_rssi)) {
4187 hddLog(LOGE, FL("nla put fail"));
4188 goto fail;
4189 }
4190
4191 cfg80211_vendor_event(skb, GFP_KERNEL);
4192 return;
4193
4194fail:
4195 kfree_skb(skb);
4196 return;
4197}
4198
4199/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
4200 * @wiphy: Pointer to wireless phy
4201 * @wdev: Pointer to wireless device
4202 * @data: Pointer to data
4203 * @data_len: Data length
4204 *
4205 * This function return the preferred frequency list generated by the policy
4206 * manager.
4207 *
4208 * Return: success or failure code
4209 */
4210static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4211 struct wireless_dev
4212 *wdev, const void *data,
4213 int data_len)
4214{
4215 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4216 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304217 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 uint8_t pcl[MAX_NUM_CHAN];
4219 uint32_t pcl_len = 0;
4220 uint32_t freq_list[MAX_NUM_CHAN];
4221 enum cds_con_mode intf_mode;
4222 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4223 struct sk_buff *reply_skb;
4224
Jeff Johnson1f61b612016-02-12 16:28:33 -08004225 ENTER_DEV(wdev->netdev);
4226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227 ret = wlan_hdd_validate_context(hdd_ctx);
4228 if (ret)
4229 return -EINVAL;
4230
4231 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4232 data, data_len, NULL)) {
4233 hdd_err("Invalid ATTR");
4234 return -EINVAL;
4235 }
4236
4237 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4238 hdd_err("attr interface type failed");
4239 return -EINVAL;
4240 }
4241
4242 intf_mode = nla_get_u32(tb
4243 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4244
4245 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4246 hdd_err("Invalid interface type");
4247 return -EINVAL;
4248 }
4249
4250 hdd_debug("Userspace requested pref freq list");
4251
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004252 status = cds_get_pcl(intf_mode, pcl, &pcl_len);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304253 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 hdd_err("Get pcl failed");
4255 return -EINVAL;
4256 }
4257
4258 /* convert channel number to frequency */
4259 for (i = 0; i < pcl_len; i++) {
4260 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4261 freq_list[i] =
4262 ieee80211_channel_to_frequency(pcl[i],
4263 IEEE80211_BAND_2GHZ);
4264 else
4265 freq_list[i] =
4266 ieee80211_channel_to_frequency(pcl[i],
4267 IEEE80211_BAND_5GHZ);
4268 }
4269
4270 /* send the freq_list back to supplicant */
4271 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4272 sizeof(u32) *
4273 pcl_len +
4274 NLMSG_HDRLEN);
4275
4276 if (!reply_skb) {
4277 hdd_err("Allocate reply_skb failed");
4278 return -EINVAL;
4279 }
4280
4281 if (nla_put_u32(reply_skb,
4282 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4283 intf_mode) ||
4284 nla_put(reply_skb,
4285 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4286 sizeof(uint32_t) * pcl_len,
4287 freq_list)) {
4288 hdd_err("nla put fail");
4289 kfree_skb(reply_skb);
4290 return -EINVAL;
4291 }
4292
4293 return cfg80211_vendor_cmd_reply(reply_skb);
4294}
4295
4296/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4297 * @wiphy: Pointer to wireless phy
4298 * @wdev: Pointer to wireless device
4299 * @data: Pointer to data
4300 * @data_len: Data length
4301 *
4302 * This function return the preferred frequency list generated by the policy
4303 * manager.
4304 *
4305 * Return: success or failure code
4306 */
4307static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4308 struct wireless_dev
4309 *wdev, const void *data,
4310 int data_len)
4311{
4312 int ret = 0;
4313
4314 cds_ssr_protect(__func__);
4315 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
4316 data, data_len);
4317 cds_ssr_unprotect(__func__);
4318
4319 return ret;
4320}
4321
4322/**
4323 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4324 * @wiphy: Pointer to wireless phy
4325 * @wdev: Pointer to wireless device
4326 * @data: Pointer to data
4327 * @data_len: Data length
4328 *
4329 * Return: 0 on success, negative errno on failure
4330 */
4331static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4332 struct wireless_dev *wdev,
4333 const void *data,
4334 int data_len)
4335{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304336 struct net_device *ndev = wdev->netdev;
4337 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4339 int ret = 0;
4340 enum cds_con_mode intf_mode;
4341 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4342 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343
Jeff Johnson1f61b612016-02-12 16:28:33 -08004344 ENTER_DEV(ndev);
4345
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346 ret = wlan_hdd_validate_context(hdd_ctx);
4347 if (ret)
4348 return ret;
4349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
4351 data, data_len, NULL)) {
4352 hdd_err("Invalid ATTR");
4353 return -EINVAL;
4354 }
4355
4356 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
4357 hdd_err("attr interface type failed");
4358 return -EINVAL;
4359 }
4360
4361 intf_mode = nla_get_u32(tb
4362 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
4363
4364 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4365 hdd_err("Invalid interface type");
4366 return -EINVAL;
4367 }
4368
4369 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
4370 hdd_err("attr probable freq failed");
4371 return -EINVAL;
4372 }
4373
4374 channel_hint = cds_freq_to_chan(nla_get_u32(tb
4375 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
4376
4377 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004378 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 channel_hint, HW_MODE_20_MHZ)) {
4380 hdd_err("Set channel hint failed due to concurrency check");
4381 return -EINVAL;
4382 }
4383
4384 if (hdd_ctx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304385 ret = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304386 if (!QDF_IS_STATUS_SUCCESS(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387 hdd_err("clearing event failed");
4388
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304389 ret = cds_current_connections_update(adapter->sessionId,
4390 channel_hint,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05304391 SIR_UPDATE_REASON_SET_OPER_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304392 if (QDF_STATUS_E_FAILURE == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004393 /* return in the failure case */
4394 hdd_err("ERROR: connections update failed!!");
4395 return -EINVAL;
4396 }
4397
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304398 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 /*
4400 * Success is the only case for which we expect hw mode
4401 * change to take place, hence we need to wait.
4402 * For any other return value it should be a pass
4403 * through
4404 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304405 ret = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406 if (!QDF_IS_STATUS_SUCCESS(ret)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304407 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 return -EINVAL;
4409 }
4410
4411 }
4412 }
4413
4414 return 0;
4415}
4416
4417/**
4418 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4419 * @wiphy: Pointer to wireless phy
4420 * @wdev: Pointer to wireless device
4421 * @data: Pointer to data
4422 * @data_len: Data length
4423 *
4424 * Return: 0 on success, negative errno on failure
4425 */
4426static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4427 struct wireless_dev *wdev,
4428 const void *data,
4429 int data_len)
4430{
4431 int ret = 0;
4432
4433 cds_ssr_protect(__func__);
4434 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
4435 data, data_len);
4436 cds_ssr_unprotect(__func__);
4437
4438 return ret;
4439}
4440
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304441static const struct
4442nla_policy
4443qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
4444 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
4445};
4446
4447/**
4448 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
4449 * @wiphy: WIPHY structure pointer
4450 * @wdev: Wireless device structure pointer
4451 * @data: Pointer to the data received
4452 * @data_len: Length of the data received
4453 *
4454 * This function is used to get link properties like nss, rate flags and
4455 * operating frequency for the active connection with the given peer.
4456 *
4457 * Return: 0 on success and errno on failure
4458 */
4459static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4460 struct wireless_dev *wdev,
4461 const void *data,
4462 int data_len)
4463{
4464 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4465 struct net_device *dev = wdev->netdev;
4466 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4467 hdd_station_ctx_t *hdd_sta_ctx;
4468 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05304469 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304470 uint32_t sta_id;
4471 struct sk_buff *reply_skb;
4472 uint32_t rate_flags = 0;
4473 uint8_t nss;
4474 uint8_t final_rate_flags = 0;
4475 uint32_t freq;
4476
Jeff Johnson1f61b612016-02-12 16:28:33 -08004477 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304478
Anurag Chouhan6d760662016-02-20 16:05:43 +05304479 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304480 hdd_err("Command not allowed in FTM mode");
4481 return -EPERM;
4482 }
4483
4484 if (0 != wlan_hdd_validate_context(hdd_ctx))
4485 return -EINVAL;
4486
4487 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
4488 qca_wlan_vendor_attr_policy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304489 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid attribute"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304490 return -EINVAL;
4491 }
4492
4493 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304494 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304495 FL("Attribute peerMac not provided for mode=%d"),
4496 adapter->device_mode);
4497 return -EINVAL;
4498 }
4499
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304500 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05304501 QDF_MAC_ADDR_SIZE);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304502 hddLog(QDF_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304503 FL("peerMac="MAC_ADDRESS_STR" for device_mode:%d"),
4504 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
4505
Krunal Sonib4326f22016-03-10 13:05:51 -08004506 if (adapter->device_mode == QDF_STA_MODE ||
4507 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304508 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4509 if ((hdd_sta_ctx->conn_info.connState !=
4510 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304511 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304512 peer_mac, QDF_MAC_ADDR_SIZE)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304513 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304514 FL("Not Associated to mac "MAC_ADDRESS_STR),
4515 MAC_ADDR_ARRAY(peer_mac));
4516 return -EINVAL;
4517 }
4518
4519 nss = hdd_sta_ctx->conn_info.nss;
4520 freq = cds_chan_to_freq(
4521 hdd_sta_ctx->conn_info.operationChannel);
4522 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08004523 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
4524 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304525
4526 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
4527 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05304528 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304529 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304530 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304531 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304532 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304533 break;
4534 }
4535
4536 if (WLAN_MAX_STA_COUNT == sta_id) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304537 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304538 FL("No active peer with mac="MAC_ADDRESS_STR),
4539 MAC_ADDR_ARRAY(peer_mac));
4540 return -EINVAL;
4541 }
4542
4543 nss = adapter->aStaInfo[sta_id].nss;
4544 freq = cds_chan_to_freq(
4545 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
4546 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
4547 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304548 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304549 FL("Not Associated! with mac "MAC_ADDRESS_STR),
4550 MAC_ADDR_ARRAY(peer_mac));
4551 return -EINVAL;
4552 }
4553
4554 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
4555 if (rate_flags & eHAL_TX_RATE_VHT80) {
4556 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004557#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304558 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004559#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304560 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
4561 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004562#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304563 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004564#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304565 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
4566 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4567 } else if (rate_flags &
4568 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
4569 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004570#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304571 if (rate_flags & eHAL_TX_RATE_HT40)
4572 final_rate_flags |=
4573 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004574#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304575 }
4576
4577 if (rate_flags & eHAL_TX_RATE_SGI) {
4578 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
4579 final_rate_flags |= RATE_INFO_FLAGS_MCS;
4580 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
4581 }
4582 }
4583
4584 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4585 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
4586
4587 if (NULL == reply_skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304588 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304589 FL("getLinkProperties: skb alloc failed"));
4590 return -EINVAL;
4591 }
4592
4593 if (nla_put_u8(reply_skb,
4594 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
4595 nss) ||
4596 nla_put_u8(reply_skb,
4597 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
4598 final_rate_flags) ||
4599 nla_put_u32(reply_skb,
4600 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
4601 freq)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304602 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla_put failed"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304603 kfree_skb(reply_skb);
4604 return -EINVAL;
4605 }
4606
4607 return cfg80211_vendor_cmd_reply(reply_skb);
4608}
4609
4610/**
4611 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
4612 * properties.
4613 * @wiphy: WIPHY structure pointer
4614 * @wdev: Wireless device structure pointer
4615 * @data: Pointer to the data received
4616 * @data_len: Length of the data received
4617 *
4618 * This function is used to get link properties like nss, rate flags and
4619 * operating frequency for the active connection with the given peer.
4620 *
4621 * Return: 0 on success and errno on failure
4622 */
4623static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4624 struct wireless_dev *wdev,
4625 const void *data,
4626 int data_len)
4627{
4628 int ret = 0;
4629
4630 cds_ssr_protect(__func__);
4631 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
4632 wdev, data, data_len);
4633 cds_ssr_unprotect(__func__);
4634
4635 return ret;
4636}
4637
Peng Xu278d0122015-09-24 16:34:17 -07004638static const struct
4639nla_policy
4640qca_wlan_vendor_ota_test_policy
4641[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
4642 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
4643};
4644
4645/**
4646 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
4647 * @wiphy: Pointer to wireless phy
4648 * @wdev: Pointer to wireless device
4649 * @data: Pointer to data
4650 * @data_len: Data length
4651 *
4652 * Return: 0 on success, negative errno on failure
4653 */
4654static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4655 struct wireless_dev *wdev,
4656 const void *data,
4657 int data_len)
4658{
4659 struct net_device *dev = wdev->netdev;
4660 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4661 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
4662 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4663 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
4664 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304665 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07004666 uint32_t current_roam_state;
4667
Jeff Johnson1f61b612016-02-12 16:28:33 -08004668 ENTER_DEV(dev);
4669
Anurag Chouhan6d760662016-02-20 16:05:43 +05304670 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07004671 hdd_err("Command not allowed in FTM mode");
4672 return -EPERM;
4673 }
4674
4675 if (0 != wlan_hdd_validate_context(hdd_ctx))
4676 return -EINVAL;
4677
4678 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
4679 data, data_len,
4680 qca_wlan_vendor_ota_test_policy)) {
4681 hdd_err("invalid attr");
4682 return -EINVAL;
4683 }
4684
4685 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
4686 hdd_err("attr ota test failed");
4687 return -EINVAL;
4688 }
4689
4690 ota_enable = nla_get_u8(
4691 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
4692
4693 hdd_info(" OTA test enable = %d", ota_enable);
4694 if (ota_enable != 1) {
4695 hdd_err("Invalid value, only enable test mode is supported!");
4696 return -EINVAL;
4697 }
4698
4699 current_roam_state =
4700 sme_get_current_roam_state(hal, adapter->sessionId);
4701 status = sme_stop_roaming(hal, adapter->sessionId,
4702 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304703 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004704 hdd_err("Enable/Disable roaming failed");
4705 return -EINVAL;
4706 }
4707
4708 status = sme_ps_enable_disable(hal, adapter->sessionId,
4709 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304710 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004711 hdd_err("Enable/Disable power save failed");
4712 /* restore previous roaming setting */
4713 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
4714 current_roam_state == eCSR_ROAMING_STATE_JOINED)
4715 status = sme_start_roaming(hal, adapter->sessionId,
4716 eCsrHddIssued);
4717 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
4718 current_roam_state == eCSR_ROAMING_STATE_IDLE)
4719 status = sme_stop_roaming(hal, adapter->sessionId,
4720 eCsrHddIssued);
4721
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304722 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07004723 hdd_err("Restoring roaming state failed");
4724
4725 return -EINVAL;
4726 }
4727
4728
4729 return 0;
4730}
4731
4732/**
4733 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
4734 * @wiphy: Pointer to wireless phy
4735 * @wdev: Pointer to wireless device
4736 * @data: Pointer to data
4737 * @data_len: Data length
4738 *
4739 * Return: 0 on success, negative errno on failure
4740 */
4741static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4742 struct wireless_dev *wdev,
4743 const void *data,
4744 int data_len)
4745{
4746 int ret = 0;
4747
4748 cds_ssr_protect(__func__);
4749 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
4750 cds_ssr_unprotect(__func__);
4751
4752 return ret;
4753}
4754
Peng Xu4d67c8f2015-10-16 16:02:26 -07004755/**
4756 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4757 * @wiphy: Pointer to wireless phy
4758 * @wdev: Pointer to wireless device
4759 * @data: Pointer to data
4760 * @data_len: Data length
4761 *
4762 * Return: 0 on success, negative errno on failure
4763 */
4764static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4765 struct wireless_dev *wdev,
4766 const void *data,
4767 int data_len)
4768{
4769 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4770 struct net_device *dev = wdev->netdev;
4771 hdd_adapter_t *adapter = NULL;
4772 int ret = 0;
4773 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
4774 uint8_t scale_value;
4775
Jeff Johnson1f61b612016-02-12 16:28:33 -08004776 ENTER_DEV(dev);
4777
Peng Xu4d67c8f2015-10-16 16:02:26 -07004778 ret = wlan_hdd_validate_context(hdd_ctx);
4779 if (ret)
4780 return ret;
4781
4782 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4783
4784 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
4785 data, data_len, NULL)) {
4786 hdd_err("Invalid ATTR");
4787 return -EINVAL;
4788 }
4789
4790 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
4791 hdd_err("attr tx power scale failed");
4792 return -EINVAL;
4793 }
4794
4795 scale_value = nla_get_u8(tb
4796 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
4797
4798 if (scale_value > MAX_TXPOWER_SCALE) {
4799 hdd_err("Invalid tx power scale level");
4800 return -EINVAL;
4801 }
4802
4803 ret = wma_set_tx_power_scale(adapter->sessionId, scale_value);
4804
4805 if (ret != 0) {
4806 hdd_err("Set tx power scale failed");
4807 return -EINVAL;
4808 }
4809
4810 return 0;
4811}
4812
4813/**
4814 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4815 * @wiphy: Pointer to wireless phy
4816 * @wdev: Pointer to wireless device
4817 * @data: Pointer to data
4818 * @data_len: Data length
4819 *
4820 * Return: 0 on success, negative errno on failure
4821 */
4822static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4823 struct wireless_dev *wdev,
4824 const void *data,
4825 int data_len)
4826{
4827 int ret = 0;
4828
4829 cds_ssr_protect(__func__);
4830 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
4831 data, data_len);
4832 cds_ssr_unprotect(__func__);
4833
4834 return ret;
4835}
4836
4837/**
4838 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4839 * @wiphy: Pointer to wireless phy
4840 * @wdev: Pointer to wireless device
4841 * @data: Pointer to data
4842 * @data_len: Data length
4843 *
4844 * Return: 0 on success, negative errno on failure
4845 */
4846static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4847 struct wireless_dev *wdev,
4848 const void *data,
4849 int data_len)
4850{
4851 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4852 struct net_device *dev = wdev->netdev;
4853 hdd_adapter_t *adapter = NULL;
4854 int ret = 0;
4855 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
4856 uint8_t scale_value;
4857
Jeff Johnson1f61b612016-02-12 16:28:33 -08004858 ENTER_DEV(dev);
4859
Peng Xu4d67c8f2015-10-16 16:02:26 -07004860 ret = wlan_hdd_validate_context(hdd_ctx);
4861 if (ret)
4862 return ret;
4863
4864 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4865
4866 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
4867 data, data_len, NULL)) {
4868 hdd_err("Invalid ATTR");
4869 return -EINVAL;
4870 }
4871
4872 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
4873 hdd_err("attr tx power decrease db value failed");
4874 return -EINVAL;
4875 }
4876
4877 scale_value = nla_get_u8(tb
4878 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
4879
4880 ret = wma_set_tx_power_scale_decr_db(adapter->sessionId, scale_value);
4881
4882 if (ret != 0) {
4883 hdd_err("Set tx power decrease db failed");
4884 return -EINVAL;
4885 }
4886
4887 return 0;
4888}
4889
4890/**
4891 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4892 * @wiphy: Pointer to wireless phy
4893 * @wdev: Pointer to wireless device
4894 * @data: Pointer to data
4895 * @data_len: Data length
4896 *
4897 * Return: 0 on success, negative errno on failure
4898 */
4899static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4900 struct wireless_dev *wdev,
4901 const void *data,
4902 int data_len)
4903{
4904 int ret = 0;
4905
4906 cds_ssr_protect(__func__);
4907 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
4908 data, data_len);
4909 cds_ssr_unprotect(__func__);
4910
4911 return ret;
4912}
4913
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
4915 {
4916 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4917 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
4918 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4919 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4920 .doit = is_driver_dfs_capable
4921 },
4922
4923#ifdef WLAN_FEATURE_NAN
4924 {
4925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
4927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4928 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4929 .doit = wlan_hdd_cfg80211_nan_request
4930 },
4931#endif
4932
4933#ifdef WLAN_FEATURE_STATS_EXT
4934 {
4935 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4936 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
4937 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4938 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4939 .doit = wlan_hdd_cfg80211_stats_ext_request
4940 },
4941#endif
4942#ifdef FEATURE_WLAN_EXTSCAN
4943 {
4944 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4945 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
4946 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4947 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4948 .doit = wlan_hdd_cfg80211_extscan_start
4949 },
4950 {
4951 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4952 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
4953 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4954 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4955 .doit = wlan_hdd_cfg80211_extscan_stop
4956 },
4957 {
4958 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4959 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
4960 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4961 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
4962 },
4963 {
4964 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4965 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
4966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4967 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4968 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
4969 },
4970 {
4971 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4972 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
4973 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4974 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4975 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
4976 },
4977 {
4978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
4980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4981 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4982 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
4983 },
4984 {
4985 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4986 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
4987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4988 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4989 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
4990 },
4991 {
4992 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4993 .info.subcmd =
4994 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
4995 .flags =
4996 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4997 WIPHY_VENDOR_CMD_NEED_RUNNING,
4998 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
4999 },
5000 {
5001 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5002 .info.subcmd =
5003 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
5004 .flags =
5005 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
5006 WIPHY_VENDOR_CMD_NEED_RUNNING,
5007 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
5008 },
5009 {
5010 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5011 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
5012 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5013 WIPHY_VENDOR_CMD_NEED_NETDEV |
5014 WIPHY_VENDOR_CMD_NEED_RUNNING,
5015 .doit = wlan_hdd_cfg80211_set_epno_list
5016 },
5017#endif /* FEATURE_WLAN_EXTSCAN */
5018
5019#ifdef WLAN_FEATURE_LINK_LAYER_STATS
5020 {
5021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5022 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
5023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5024 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5025 .doit = wlan_hdd_cfg80211_ll_stats_clear
5026 },
5027
5028 {
5029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
5031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5032 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5033 .doit = wlan_hdd_cfg80211_ll_stats_set
5034 },
5035
5036 {
5037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
5039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5040 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5041 .doit = wlan_hdd_cfg80211_ll_stats_get
5042 },
5043#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
5044#ifdef FEATURE_WLAN_TDLS
5045 {
5046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
5048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5049 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5050 .doit = wlan_hdd_cfg80211_exttdls_enable
5051 },
5052 {
5053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
5055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5056 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5057 .doit = wlan_hdd_cfg80211_exttdls_disable
5058 },
5059 {
5060 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5061 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
5062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5063 .doit = wlan_hdd_cfg80211_exttdls_get_status
5064 },
5065#endif
5066 {
5067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5068 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
5069 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5070 .doit = wlan_hdd_cfg80211_get_supported_features
5071 },
5072 {
5073 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5074 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
5075 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5076 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
5077 },
5078 {
5079 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5080 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
5081 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05305082 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005083 },
5084 {
5085 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5086 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
5087 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5088 WIPHY_VENDOR_CMD_NEED_NETDEV,
5089 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
5090 },
5091
5092 {
5093 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5094 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
5095 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5096 WIPHY_VENDOR_CMD_NEED_NETDEV |
5097 WIPHY_VENDOR_CMD_NEED_RUNNING,
5098 .doit = wlan_hdd_cfg80211_do_acs
5099 },
5100
5101 {
5102 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5103 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
5104 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5105 WIPHY_VENDOR_CMD_NEED_NETDEV,
5106 .doit = wlan_hdd_cfg80211_get_features
5107 },
5108#ifdef WLAN_FEATURE_ROAM_OFFLOAD
5109 {
5110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5111 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
5112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5113 WIPHY_VENDOR_CMD_NEED_NETDEV |
5114 WIPHY_VENDOR_CMD_NEED_RUNNING,
5115 .doit = wlan_hdd_cfg80211_keymgmt_set_key
5116 },
5117#endif
5118#ifdef FEATURE_WLAN_EXTSCAN
5119 {
5120 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5121 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
5122 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5123 WIPHY_VENDOR_CMD_NEED_NETDEV |
5124 WIPHY_VENDOR_CMD_NEED_RUNNING,
5125 .doit = wlan_hdd_cfg80211_set_passpoint_list
5126 },
5127 {
5128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
5130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5131 WIPHY_VENDOR_CMD_NEED_NETDEV |
5132 WIPHY_VENDOR_CMD_NEED_RUNNING,
5133 .doit = wlan_hdd_cfg80211_reset_passpoint_list
5134 },
5135 {
5136 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5137 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
5138 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5139 WIPHY_VENDOR_CMD_NEED_NETDEV |
5140 WIPHY_VENDOR_CMD_NEED_RUNNING,
5141 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
5142 },
5143 {
5144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
5146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5147 WIPHY_VENDOR_CMD_NEED_NETDEV |
5148 WIPHY_VENDOR_CMD_NEED_RUNNING,
5149 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
5150 },
5151#endif /* FEATURE_WLAN_EXTSCAN */
5152 {
5153 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5154 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
5155 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5156 WIPHY_VENDOR_CMD_NEED_NETDEV,
5157 .doit = wlan_hdd_cfg80211_get_wifi_info
5158 },
5159 {
5160 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5161 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
5162 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5163 WIPHY_VENDOR_CMD_NEED_NETDEV |
5164 WIPHY_VENDOR_CMD_NEED_RUNNING,
5165 .doit = wlan_hdd_cfg80211_wifi_configuration_set
5166 },
5167 {
5168 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5169 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
5170 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5171 WIPHY_VENDOR_CMD_NEED_NETDEV,
5172 .doit = wlan_hdd_cfg80211_set_ext_roam_params
5173 },
5174 {
5175 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5176 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
5177 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5178 WIPHY_VENDOR_CMD_NEED_NETDEV,
5179 .doit = wlan_hdd_cfg80211_wifi_logger_start
5180 },
5181 {
5182 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5183 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
5184 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5185 WIPHY_VENDOR_CMD_NEED_NETDEV,
5186 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
5187 },
5188 {
5189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5190 .info.subcmd =
5191 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
5192 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5193 WIPHY_VENDOR_CMD_NEED_NETDEV |
5194 WIPHY_VENDOR_CMD_NEED_RUNNING,
5195 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
5196 },
5197 {
5198 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5199 .info.subcmd =
5200 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
5201 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5202 WIPHY_VENDOR_CMD_NEED_NETDEV |
5203 WIPHY_VENDOR_CMD_NEED_RUNNING,
5204 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
5205 },
5206#ifdef FEATURE_WLAN_TDLS
5207 {
5208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
5210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5211 WIPHY_VENDOR_CMD_NEED_NETDEV |
5212 WIPHY_VENDOR_CMD_NEED_RUNNING,
5213 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
5214 },
5215#endif
5216#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5217 {
5218 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5219 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
5220 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5221 WIPHY_VENDOR_CMD_NEED_NETDEV |
5222 WIPHY_VENDOR_CMD_NEED_RUNNING,
5223 .doit = wlan_hdd_cfg80211_offloaded_packets
5224 },
5225#endif
5226 {
5227 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5228 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
5229 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5230 WIPHY_VENDOR_CMD_NEED_NETDEV |
5231 WIPHY_VENDOR_CMD_NEED_RUNNING,
5232 .doit = wlan_hdd_cfg80211_monitor_rssi
5233 },
5234 {
5235 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5236 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
5237 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5238 WIPHY_VENDOR_CMD_NEED_NETDEV |
5239 WIPHY_VENDOR_CMD_NEED_RUNNING,
5240 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
5241 },
5242#ifdef WLAN_FEATURE_MEMDUMP
5243 {
5244 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5245 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
5246 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5247 WIPHY_VENDOR_CMD_NEED_NETDEV |
5248 WIPHY_VENDOR_CMD_NEED_RUNNING,
5249 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
5250 },
5251#endif /* WLAN_FEATURE_MEMDUMP */
5252 {
5253 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5254 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
5255 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5256 WIPHY_VENDOR_CMD_NEED_NETDEV |
5257 WIPHY_VENDOR_CMD_NEED_RUNNING,
5258 .doit = wlan_hdd_cfg80211_vendor_scan
5259 },
5260
5261 /* OCB commands */
5262 {
5263 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5264 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
5265 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5266 WIPHY_VENDOR_CMD_NEED_NETDEV |
5267 WIPHY_VENDOR_CMD_NEED_RUNNING,
5268 .doit = wlan_hdd_cfg80211_ocb_set_config
5269 },
5270 {
5271 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5272 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
5273 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5274 WIPHY_VENDOR_CMD_NEED_NETDEV |
5275 WIPHY_VENDOR_CMD_NEED_RUNNING,
5276 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
5277 },
5278 {
5279 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5280 .info.subcmd =
5281 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
5282 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5283 WIPHY_VENDOR_CMD_NEED_NETDEV |
5284 WIPHY_VENDOR_CMD_NEED_RUNNING,
5285 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
5286 },
5287 {
5288 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5289 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
5290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5291 WIPHY_VENDOR_CMD_NEED_NETDEV |
5292 WIPHY_VENDOR_CMD_NEED_RUNNING,
5293 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
5294 },
5295 {
5296 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5297 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
5298 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5299 WIPHY_VENDOR_CMD_NEED_NETDEV |
5300 WIPHY_VENDOR_CMD_NEED_RUNNING,
5301 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
5302 },
5303 {
5304 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5305 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
5306 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5307 WIPHY_VENDOR_CMD_NEED_NETDEV |
5308 WIPHY_VENDOR_CMD_NEED_RUNNING,
5309 .doit = wlan_hdd_cfg80211_dcc_get_stats
5310 },
5311 {
5312 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5313 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
5314 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5315 WIPHY_VENDOR_CMD_NEED_NETDEV |
5316 WIPHY_VENDOR_CMD_NEED_RUNNING,
5317 .doit = wlan_hdd_cfg80211_dcc_clear_stats
5318 },
5319 {
5320 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5321 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
5322 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5323 WIPHY_VENDOR_CMD_NEED_NETDEV |
5324 WIPHY_VENDOR_CMD_NEED_RUNNING,
5325 .doit = wlan_hdd_cfg80211_dcc_update_ndl
5326 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305327 {
5328 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5329 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
5330 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5331 WIPHY_VENDOR_CMD_NEED_NETDEV |
5332 WIPHY_VENDOR_CMD_NEED_RUNNING,
5333 .doit = wlan_hdd_cfg80211_get_link_properties
5334 },
Peng Xu278d0122015-09-24 16:34:17 -07005335 {
5336 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
5337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5338 WIPHY_VENDOR_CMD_NEED_NETDEV |
5339 WIPHY_VENDOR_CMD_NEED_RUNNING,
5340 .doit = wlan_hdd_cfg80211_set_ota_test
5341 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08005342#ifdef FEATURE_LFR_SUBNET_DETECTION
5343 {
5344 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5345 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
5346 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5347 WIPHY_VENDOR_CMD_NEED_NETDEV |
5348 WIPHY_VENDOR_CMD_NEED_RUNNING,
5349 .doit = wlan_hdd_cfg80211_set_gateway_params
5350 },
5351#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07005352 {
5353 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
5354 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5355 WIPHY_VENDOR_CMD_NEED_NETDEV |
5356 WIPHY_VENDOR_CMD_NEED_RUNNING,
5357 .doit = wlan_hdd_cfg80211_txpower_scale
5358 },
5359 {
5360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5361 .info.subcmd =
5362 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
5363 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5364 WIPHY_VENDOR_CMD_NEED_NETDEV |
5365 WIPHY_VENDOR_CMD_NEED_RUNNING,
5366 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
5367 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368};
5369
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005370/**
5371 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
5372 * @priv_size: Size of the hdd context.
5373 *
5374 * Allocate wiphy context and hdd context.
5375 *
5376 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005378hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379{
5380 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005381 hdd_context_t *hdd_ctx;
5382
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 ENTER();
5384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
5386
5387 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005388 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 return NULL;
5390 }
5391
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08005392 hdd_ctx = wiphy_priv(wiphy);
5393
5394 hdd_ctx->wiphy = wiphy;
5395
5396 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397}
5398
5399/*
5400 * FUNCTION: wlan_hdd_cfg80211_update_band
5401 * This function is called from the supplicant through a
5402 * private ioctl to change the band value
5403 */
5404int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
5405{
5406 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07005407 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408
5409 ENTER();
5410
5411 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5412
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005413 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005414 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005415
5416 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5417 struct ieee80211_supported_band *band = wiphy->bands[i];
5418
5419 channelEnabledState =
5420 cds_get_channel_state(band->channels[j].
5421 hw_value);
5422
5423 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
5424 /* 5G only */
5425#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5426 /* Enable Social channels for P2P */
5427 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5428 (band->channels[j].center_freq)
5429 && CHANNEL_STATE_ENABLE ==
5430 channelEnabledState)
5431 band->channels[j].flags &=
5432 ~IEEE80211_CHAN_DISABLED;
5433 else
5434#endif
5435 band->channels[j].flags |=
5436 IEEE80211_CHAN_DISABLED;
5437 continue;
5438 } else if (IEEE80211_BAND_5GHZ == i &&
5439 eCSR_BAND_24 == eBand) {
5440 /* 2G only */
5441 band->channels[j].flags |=
5442 IEEE80211_CHAN_DISABLED;
5443 continue;
5444 }
5445
Amar Singhal6842e8f2016-02-23 16:30:32 -08005446 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447 band->channels[j].flags &=
5448 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 }
5450 }
5451 return 0;
5452}
5453
5454/*
5455 * FUNCTION: wlan_hdd_cfg80211_init
5456 * This function is called by hdd_wlan_startup()
5457 * during initialization.
5458 * This function is used to initialize and register wiphy structure.
5459 */
5460int wlan_hdd_cfg80211_init(struct device *dev,
5461 struct wiphy *wiphy, struct hdd_config *pCfg)
5462{
5463 int i, j;
5464 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5465
5466 ENTER();
5467
5468 /* Now bind the underlying wlan device with wiphy */
5469 set_wiphy_dev(wiphy, dev);
5470
5471 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
5472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005473#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
5474 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005475 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476#else
5477 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07005478 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479#endif
5480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
5482 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
5483 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
5484#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
5485 | WIPHY_FLAG_4ADDR_STATION
5486#endif
5487 | WIPHY_FLAG_OFFCHAN_TX;
5488
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005489#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
5490 wiphy->wowlan = &wowlan_support_cfg80211_init;
5491#else
5492 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
5493 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
5494 wiphy->wowlan.pattern_min_len = 1;
5495 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
5496#endif
5497
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07005498 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005499#ifdef FEATURE_WLAN_ESE
5500 || pCfg->isEseIniFeatureEnabled
5501#endif
5502 ) {
5503 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
5504 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005505#ifdef FEATURE_WLAN_TDLS
5506 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
5507 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
5508#endif
5509
5510 wiphy->features |= NL80211_FEATURE_HT_IBSS;
5511
5512#ifdef FEATURE_WLAN_SCAN_PNO
5513 if (pCfg->configPNOScanSupport) {
5514 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5515 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
5516 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
5517 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
5518 }
5519#endif /*FEATURE_WLAN_SCAN_PNO */
5520
5521#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05305522 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523#endif
5524
5525 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
5526 driver can still register regulatory callback and
5527 it will get regulatory settings in wiphy->band[], but
5528 driver need to determine what to do with both
5529 regulatory settings */
5530
5531 wiphy->reg_notifier = hdd_reg_notifier;
5532
5533#if defined QCA_WIFI_FTM
5534}
5535#endif
5536
5537 wiphy->max_scan_ssids = MAX_SCAN_SSID;
5538
5539 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
5540
5541 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
5542
5543 /* Supports STATION & AD-HOC modes right now */
5544 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
5545 | BIT(NL80211_IFTYPE_ADHOC)
5546 | BIT(NL80211_IFTYPE_P2P_CLIENT)
5547 | BIT(NL80211_IFTYPE_P2P_GO)
5548 | BIT(NL80211_IFTYPE_AP);
5549
5550 if (pCfg->advertiseConcurrentOperation) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005551 if (pCfg->enableMCC) {
5552 int i;
5553 for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination);
5554 i++) {
5555 if (!pCfg->allowMCCGODiffBI)
5556 wlan_hdd_iface_combination[i].
5557 beacon_int_infra_match = true;
5558 }
5559 }
5560 wiphy->n_iface_combinations =
5561 ARRAY_SIZE(wlan_hdd_iface_combination);
5562 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005563 }
5564
5565 /* Before registering we need to update the ht capabilitied based
5566 * on ini values*/
5567 if (!pCfg->ShortGI20MhzEnable) {
5568 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5569 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
5570 wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &=
5571 ~IEEE80211_HT_CAP_SGI_20;
5572 }
5573
5574 if (!pCfg->ShortGI40MhzEnable) {
5575 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
5576 }
5577
5578 if (!pCfg->nChannelBondingMode5GHz) {
5579 wlan_hdd_band_5_ghz.ht_cap.cap &=
5580 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
5581 }
5582
5583 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
5584 if (true == hdd_is_5g_supported(pHddCtx)) {
5585 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
5586 }
5587
5588 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
5589
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08005590 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005591 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592
5593 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
5594 struct ieee80211_supported_band *band = wiphy->bands[i];
5595
5596 if (IEEE80211_BAND_2GHZ == i &&
5597 eCSR_BAND_5G == pCfg->nBandCapability) {
5598 /* 5G only */
5599#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
5600 /* Enable social channels for P2P */
5601 if (WLAN_HDD_IS_SOCIAL_CHANNEL
5602 (band->channels[j].center_freq))
5603 band->channels[j].flags &=
5604 ~IEEE80211_CHAN_DISABLED;
5605 else
5606#endif
5607 band->channels[j].flags |=
5608 IEEE80211_CHAN_DISABLED;
5609 continue;
5610 } else if (IEEE80211_BAND_5GHZ == i &&
5611 eCSR_BAND_24 == pCfg->nBandCapability) {
5612 /* 2G only */
5613 band->channels[j].flags |=
5614 IEEE80211_CHAN_DISABLED;
5615 continue;
5616 }
5617 }
5618 }
5619 /*Initialise the supported cipher suite details */
5620 wiphy->cipher_suites = hdd_cipher_suites;
5621 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
5622
5623 /*signal strength in mBm (100*dBm) */
5624 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
5625 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
5626
Anurag Chouhan6d760662016-02-20 16:05:43 +05305627 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005628 wiphy->n_vendor_commands =
5629 ARRAY_SIZE(hdd_wiphy_vendor_commands);
5630 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
5631
5632 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
5633 wiphy->n_vendor_events =
5634 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
5635 }
5636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637 if (pCfg->enableDFSMasterCap) {
5638 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
5639 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005640
5641 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
5642
5643#ifdef QCA_HT_2040_COEX
5644 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
5645#endif
5646
Abhishek Singh1bdb1572015-10-16 16:24:19 +05305647 hdd_add_channel_switch_support(&wiphy->flags);
5648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649 EXIT();
5650 return 0;
5651}
5652
5653/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05305654 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655 * initialization. In wlan_hdd_cfg80211_init, only the
5656 * default values will be initialized. The final initialization
5657 * of all required members can be done here.
5658 */
5659void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
5660{
5661 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
5662}
5663
5664/* In this function we are registering wiphy. */
5665int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
5666{
5667 ENTER();
5668 /* Register our wiphy dev with cfg80211 */
5669 if (0 > wiphy_register(wiphy)) {
5670 /* print error */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305671 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: wiphy register failed",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005672 __func__);
5673 return -EIO;
5674 }
5675
5676 EXIT();
5677 return 0;
5678}
5679
5680/*
5681 HDD function to update wiphy capability based on target offload status.
5682
5683 wlan_hdd_cfg80211_init() does initialization of all wiphy related
5684 capability even before downloading firmware to the target. In discrete
5685 case, host will get know certain offload capability (say sched_scan
5686 caps) only after downloading firmware to the target and target boots up.
5687 This function is used to override setting done in wlan_hdd_cfg80211_init()
5688 based on target capability.
5689 */
5690void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
5691{
5692#ifdef FEATURE_WLAN_SCAN_PNO
5693 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5694 struct hdd_config *pCfg = pHddCtx->config;
5695
5696 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
5697 * control comes here. Here just we need to clear it if firmware doesn't
5698 * have PNO support. */
5699 if (!pCfg->PnoOffload) {
5700 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5701 wiphy->max_sched_scan_ssids = 0;
5702 wiphy->max_match_sets = 0;
5703 wiphy->max_sched_scan_ie_len = 0;
5704 }
5705#endif
5706}
5707
5708/* This function registers for all frame which supplicant is interested in */
5709void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
5710{
5711 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5712 /* Register for all P2P action, public action etc frames */
5713 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5714
5715 ENTER();
5716
Abhishek Singh7996eb72015-12-30 17:24:02 +05305717 /* Register frame indication call back */
5718 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
5719
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005720 /* Right now we are registering these frame when driver is getting
5721 initialized. Once we will move to 2.6.37 kernel, in which we have
5722 frame register ops, we will move this code as a part of that */
5723 /* GAS Initial Request */
5724 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5725 (uint8_t *) GAS_INITIAL_REQ,
5726 GAS_INITIAL_REQ_SIZE);
5727
5728 /* GAS Initial Response */
5729 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5730 (uint8_t *) GAS_INITIAL_RSP,
5731 GAS_INITIAL_RSP_SIZE);
5732
5733 /* GAS Comeback Request */
5734 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5735 (uint8_t *) GAS_COMEBACK_REQ,
5736 GAS_COMEBACK_REQ_SIZE);
5737
5738 /* GAS Comeback Response */
5739 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5740 (uint8_t *) GAS_COMEBACK_RSP,
5741 GAS_COMEBACK_RSP_SIZE);
5742
5743 /* P2P Public Action */
5744 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5745 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5746 P2P_PUBLIC_ACTION_FRAME_SIZE);
5747
5748 /* P2P Action */
5749 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5750 (uint8_t *) P2P_ACTION_FRAME,
5751 P2P_ACTION_FRAME_SIZE);
5752
5753 /* WNM BSS Transition Request frame */
5754 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5755 (uint8_t *) WNM_BSS_ACTION_FRAME,
5756 WNM_BSS_ACTION_FRAME_SIZE);
5757
5758 /* WNM-Notification */
5759 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
5760 (uint8_t *) WNM_NOTIFICATION_FRAME,
5761 WNM_NOTIFICATION_FRAME_SIZE);
5762}
5763
5764void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
5765{
5766 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5767 /* Register for all P2P action, public action etc frames */
5768 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5769
5770 ENTER();
5771
5772 /* Right now we are registering these frame when driver is getting
5773 initialized. Once we will move to 2.6.37 kernel, in which we have
5774 frame register ops, we will move this code as a part of that */
5775 /* GAS Initial Request */
5776
5777 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5778 (uint8_t *) GAS_INITIAL_REQ,
5779 GAS_INITIAL_REQ_SIZE);
5780
5781 /* GAS Initial Response */
5782 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5783 (uint8_t *) GAS_INITIAL_RSP,
5784 GAS_INITIAL_RSP_SIZE);
5785
5786 /* GAS Comeback Request */
5787 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5788 (uint8_t *) GAS_COMEBACK_REQ,
5789 GAS_COMEBACK_REQ_SIZE);
5790
5791 /* GAS Comeback Response */
5792 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5793 (uint8_t *) GAS_COMEBACK_RSP,
5794 GAS_COMEBACK_RSP_SIZE);
5795
5796 /* P2P Public Action */
5797 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5798 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5799 P2P_PUBLIC_ACTION_FRAME_SIZE);
5800
5801 /* P2P Action */
5802 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5803 (uint8_t *) P2P_ACTION_FRAME,
5804 P2P_ACTION_FRAME_SIZE);
5805
5806 /* WNM-Notification */
5807 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
5808 (uint8_t *) WNM_NOTIFICATION_FRAME,
5809 WNM_NOTIFICATION_FRAME_SIZE);
5810}
5811
5812#ifdef FEATURE_WLAN_WAPI
5813void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
5814 const uint8_t *mac_addr, const uint8_t *key,
5815 int key_Len)
5816{
5817 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5818 tCsrRoamSetKey setKey;
5819 bool isConnected = true;
5820 int status = 0;
5821 uint32_t roamId = 0xFF;
5822 uint8_t *pKeyPtr = NULL;
5823 int n = 0;
5824
5825 hddLog(LOG1, "Device_mode %s(%d)",
5826 hdd_device_mode_to_string(pAdapter->device_mode),
5827 pAdapter->device_mode);
5828
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305829 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830 setKey.keyId = key_index; /* Store Key ID */
5831 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
5832 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
5833 setKey.paeRole = 0; /* the PAE role */
5834 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05305835 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305837 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005838 }
5839 setKey.keyLength = key_Len;
5840 pKeyPtr = setKey.Key;
5841 memcpy(pKeyPtr, key, key_Len);
5842
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305843 hddLog(QDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 __func__, key_Len);
5845 for (n = 0; n < key_Len; n++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305846 hddLog(QDF_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005847 __func__, n, setKey.Key[n]);
5848
5849 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
5850 if (isConnected) {
5851 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
5852 pAdapter->sessionId, &setKey, &roamId);
5853 }
5854 if (status != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305855 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 "[%4d] sme_roam_set_key returned ERROR status= %d",
5857 __LINE__, status);
5858 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
5859 }
5860}
5861#endif /* FEATURE_WLAN_WAPI */
5862
5863uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
5864 uint8_t eid)
5865{
5866 int left = length;
5867 uint8_t *ptr = (uint8_t *)ies_ptr;
5868 uint8_t elem_id, elem_len;
5869
5870 while (left >= 2) {
5871 elem_id = ptr[0];
5872 elem_len = ptr[1];
5873 left -= 2;
5874 if (elem_len > left) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305875 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876 FL("Invalid IEs eid = %d elem_len=%d left=%d"),
5877 eid, elem_len, left);
5878 return NULL;
5879 }
5880 if (elem_id == eid) {
5881 return ptr;
5882 }
5883
5884 left -= elem_len;
5885 ptr += (elem_len + 2);
5886 }
5887 return NULL;
5888}
5889
5890/*
5891 * FUNCTION: wlan_hdd_validate_operation_channel
5892 * called by wlan_hdd_cfg80211_start_bss() and
5893 * wlan_hdd_set_channel()
5894 * This function validates whether given channel is part of valid
5895 * channel list.
5896 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305897QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005898 int channel)
5899{
5900
5901 uint32_t num_ch = 0;
5902 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5903 u32 indx = 0;
5904 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5905 uint8_t fValidChannel = false, count = 0;
5906 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
5907
5908 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5909
5910 if (hdd_pConfig_ini->sapAllowAllChannel) {
5911 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08005912 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07005913 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005914 fValidChannel = true;
5915 break;
5916 }
5917 }
5918 if (fValidChannel != true) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305919 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005920 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305921 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 }
5923 } else {
5924 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5925 valid_ch, &num_ch)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305926 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 "%s: failed to get valid channel list",
5928 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305929 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930 }
5931 for (indx = 0; indx < num_ch; indx++) {
5932 if (channel == valid_ch[indx]) {
5933 break;
5934 }
5935 }
5936
5937 if (indx >= num_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305938 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005939 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305940 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 }
5942 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305943 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005944
5945}
5946
5947#ifdef DHCP_SERVER_OFFLOAD
5948static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
5949{
5950 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
5951 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
5952 uint8_t numEntries = 0;
5953 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
5954 uint8_t num;
5955 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305956 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005957 if (NULL == pDhcpSrvInfo) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305958 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005959 "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
5960 return;
5961 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305962 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005963 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
5964 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
5965 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
5966 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
5967 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
5968 if (numEntries != IPADDR_NUM_ENTRIES) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305969 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005970 "%s: incorrect IP address (%s) assigned for DHCP server!",
5971 __func__, pHddCtx->config->dhcpServerIP);
5972 goto end;
5973 }
5974 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305975 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005976 "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
5977 __func__, pHddCtx->config->dhcpServerIP);
5978 goto end;
5979 }
5980 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305981 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005982 "%s: invalid IP address (%s)! The last field must be less than 100!",
5983 __func__, pHddCtx->config->dhcpServerIP);
5984 goto end;
5985 }
5986 for (num = 0; num < numEntries; num++) {
5987 temp = srv_ip[num];
5988 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
5989 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305990 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305992 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005993 "%s: sme_setDHCPSrvOffload fail!", __func__);
5994 goto end;
5995 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305996 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005997 "%s: enable DHCP Server offload successfully!", __func__);
5998end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305999 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006000 return;
6001}
6002#endif /* DHCP_SERVER_OFFLOAD */
6003
6004static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6005 struct net_device *dev,
6006 struct bss_parameters *params)
6007{
6008 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6009 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6010 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306011 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012
6013 ENTER();
6014
Anurag Chouhan6d760662016-02-20 16:05:43 +05306015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006016 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6017 return -EINVAL;
6018 }
6019
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306020 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006021 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
6022 pAdapter->sessionId, params->ap_isolate));
6023 hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"),
6024 hdd_device_mode_to_string(pAdapter->device_mode),
6025 pAdapter->device_mode, params->ap_isolate);
6026
6027 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6028 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306029 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031
Krunal Sonib4326f22016-03-10 13:05:51 -08006032 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
6033 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034 return -EOPNOTSUPP;
6035 }
6036
6037 /* ap_isolate == -1 means that in change bss, upper layer doesn't
6038 * want to update this parameter */
6039 if (-1 != params->ap_isolate) {
6040 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
6041 !!params->ap_isolate;
6042
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306043 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006044 pAdapter->sessionId,
6045 pAdapter->sessionCtx.
6046 ap.
6047 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306048 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049 ret = -EINVAL;
6050 }
6051 }
6052
6053 EXIT();
6054 return ret;
6055}
6056
Krunal Soni8c37e322016-02-03 16:08:37 -08006057/**
6058 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
6059 * @ndev: pointer to net device provided by supplicant
6060 * @type: type of the interface, upper layer wanted to change
6061 *
6062 * Upper layer provides the new interface mode that needs to be changed
6063 * for given net device
6064 *
6065 * Return: success or failure in terms of integer value
6066 */
6067static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006068 enum nl80211_iftype type)
6069{
Krunal Soni8c37e322016-02-03 16:08:37 -08006070 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6071 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6072 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 hdd_wext_state_t *wext;
6074 struct wireless_dev *wdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306075 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076
6077 ENTER();
6078
Krunal Soni8c37e322016-02-03 16:08:37 -08006079 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006080 hddLog(LOG1, FL("ACS is in progress, don't change iface!"));
6081 return 0;
6082 }
6083
6084 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08006085 hdd_stop_adapter(hdd_ctx, adapter, true);
6086 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006087 wdev->iftype = type;
6088 /*Check for sub-string p2p to confirm its a p2p interface */
6089 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08006090 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006092 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08006093 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08006094 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08006096 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006098 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006099 }
Krunal Soni8c37e322016-02-03 16:08:37 -08006100 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
6101 hdd_set_station_ops(adapter->dev);
6102 status = hdd_init_station_mode(adapter);
6103 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
6104 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006105 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08006106 adapter->scan_info.scanAddIE.length;
6107 if (type == NL80211_IFTYPE_ADHOC) {
6108 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
6109 wext->roamProfile.phyMode =
6110 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
6111 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006112 EXIT();
6113 return status;
6114}
6115
6116static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6117 struct net_device *dev,
6118 struct bss_parameters *params)
6119{
6120 int ret;
6121
6122 cds_ssr_protect(__func__);
6123 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
6124 cds_ssr_unprotect(__func__);
6125
6126 return ret;
6127}
6128
6129/* FUNCTION: wlan_hdd_change_country_code_cd
6130 * to wait for contry code completion
6131 */
6132void *wlan_hdd_change_country_code_cb(void *pAdapter)
6133{
6134 hdd_adapter_t *call_back_pAdapter = pAdapter;
6135 complete(&call_back_pAdapter->change_country_code);
6136 return NULL;
6137}
6138
Rajeev Kumar98edb772016-01-19 12:42:19 -08006139/**
6140 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6141 * @wiphy: Pointer to the wiphy structure
6142 * @ndev: Pointer to the net device
6143 * @type: Interface type
6144 * @flags: Flags for change interface
6145 * @params: Pointer to change interface parameters
6146 *
6147 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006148 */
6149static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6150 struct net_device *ndev,
6151 enum nl80211_iftype type,
6152 u32 *flags,
6153 struct vif_params *params)
6154{
6155 struct wireless_dev *wdev;
6156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6157 hdd_context_t *pHddCtx;
6158 tCsrRoamProfile *pRoamProfile = NULL;
6159 eCsrRoamBssType LastBSSType;
6160 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306161 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 int status;
6163
6164 ENTER();
6165
Anurag Chouhan6d760662016-02-20 16:05:43 +05306166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006167 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6168 return -EINVAL;
6169 }
6170
6171 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6172 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306173 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006175
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306176 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006177 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
6178 pAdapter->sessionId, type));
6179
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306180 hddLog(QDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006181 pAdapter->device_mode, type);
6182
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006183 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006184 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
6185 0, HW_MODE_20_MHZ)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306186 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006187 FL("This concurrency combination is not allowed"));
6188 return -EINVAL;
6189 }
6190
6191 pConfig = pHddCtx->config;
6192 wdev = ndev->ieee80211_ptr;
6193
6194 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006195 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006196
6197 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
6198
Krunal Sonib4326f22016-03-10 13:05:51 -08006199 if ((pAdapter->device_mode == QDF_STA_MODE) ||
6200 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
6201 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
6202 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006203 hdd_wext_state_t *pWextState =
6204 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6205
6206 pRoamProfile = &pWextState->roamProfile;
6207 LastBSSType = pRoamProfile->BSSType;
6208
6209 switch (type) {
6210 case NL80211_IFTYPE_STATION:
6211 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08006212 case NL80211_IFTYPE_ADHOC:
6213 if (type == NL80211_IFTYPE_ADHOC) {
6214 wlan_hdd_tdls_exit(pAdapter);
6215 hdd_deregister_tx_flow_control(pAdapter);
6216 hddLog(LOG1,
6217 FL("Setting interface Type to ADHOC"));
6218 }
6219 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
6220 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306221 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006222 return -EINVAL;
6223
Krunal Soni8c37e322016-02-03 16:08:37 -08006224 /*
6225 * for ibss interface type flow control is not required
6226 * so don't register tx flow control
6227 */
6228 if (type != NL80211_IFTYPE_ADHOC)
6229 hdd_register_tx_flow_control(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006230 hdd_tx_resume_timer_expired_handler,
6231 hdd_tx_resume_cb);
6232
6233 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006234 case NL80211_IFTYPE_AP:
6235 case NL80211_IFTYPE_P2P_GO:
6236 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306237 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006238 FL("Setting interface Type to %s"),
6239 (type ==
6240 NL80211_IFTYPE_AP) ? "SoftAP" :
6241 "P2pGo");
6242
6243 /* Cancel any remain on channel for GO mode */
6244 if (NL80211_IFTYPE_P2P_GO == type) {
6245 wlan_hdd_cancel_existing_remain_on_channel
6246 (pAdapter);
6247 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006248 hdd_stop_adapter(pHddCtx, pAdapter, true);
6249
6250 /* De-init the adapter */
6251 hdd_deinit_adapter(pHddCtx, pAdapter, true);
6252 memset(&pAdapter->sessionCtx, 0,
6253 sizeof(pAdapter->sessionCtx));
6254 pAdapter->device_mode =
6255 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08006256 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
6257 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006258
6259 /*
6260 * Fw will take care incase of concurrency
6261 */
6262
Krunal Sonib4326f22016-03-10 13:05:51 -08006263 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006264 && (pConfig->apRandomBssidEnabled)) {
6265 /* To meet Android requirements create a randomized
6266 MAC address of the form 02:1A:11:Fx:xx:xx */
6267 get_random_bytes(&ndev->dev_addr[3], 3);
6268 ndev->dev_addr[0] = 0x02;
6269 ndev->dev_addr[1] = 0x1A;
6270 ndev->dev_addr[2] = 0x11;
6271 ndev->dev_addr[3] |= 0xF0;
6272 memcpy(pAdapter->macAddressCurrent.
6273 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306274 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006275 pr_info("wlan: Generated HotSpot BSSID "
6276 MAC_ADDRESS_STR "\n",
6277 MAC_ADDR_ARRAY(ndev->dev_addr));
6278 }
6279
6280 hdd_set_ap_ops(pAdapter->dev);
6281
6282 vstatus = hdd_init_ap_mode(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306283 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006284 hddLog(LOGP,
6285 FL
6286 ("Error initializing the ap mode"));
6287 return -EINVAL;
6288 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006289
6290 hdd_register_tx_flow_control(pAdapter,
6291 hdd_softap_tx_resume_timer_expired_handler,
6292 hdd_softap_tx_resume_cb);
6293
6294 /* Interface type changed update in wiphy structure */
6295 if (wdev) {
6296 wdev->iftype = type;
6297 } else {
6298 hddLog(LOGE,
6299 FL("Wireless dev is NULL"));
6300 return -EINVAL;
6301 }
6302 goto done;
6303 }
6304
6305 default:
6306 hddLog(LOGE, FL("Unsupported interface type (%d)"),
6307 type);
6308 return -EOPNOTSUPP;
6309 }
Krunal Sonib4326f22016-03-10 13:05:51 -08006310 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
6311 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006312 switch (type) {
6313 case NL80211_IFTYPE_STATION:
6314 case NL80211_IFTYPE_P2P_CLIENT:
6315 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08006316 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
6317 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306318 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006319 return status;
6320
6321 if ((NL80211_IFTYPE_P2P_CLIENT == type) ||
6322 (NL80211_IFTYPE_STATION == type)) {
6323
6324 hdd_register_tx_flow_control(pAdapter,
6325 hdd_tx_resume_timer_expired_handler,
6326 hdd_tx_resume_cb);
6327 }
6328 goto done;
6329
6330 case NL80211_IFTYPE_AP:
6331 case NL80211_IFTYPE_P2P_GO:
6332 wdev->iftype = type;
6333 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006334 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006335
6336 hdd_register_tx_flow_control(pAdapter,
6337 hdd_softap_tx_resume_timer_expired_handler,
6338 hdd_softap_tx_resume_cb);
6339 goto done;
6340
6341 default:
6342 hddLog(LOGE, FL("Unsupported interface type(%d)"),
6343 type);
6344 return -EOPNOTSUPP;
6345 }
6346 } else {
6347 hddLog(LOGE, FL("Unsupported device mode(%d)"),
6348 pAdapter->device_mode);
6349 return -EOPNOTSUPP;
6350 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006351done:
6352 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006353 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006354
6355#ifdef WLAN_FEATURE_LPSS
6356 wlan_hdd_send_all_scan_intf_info(pHddCtx);
6357#endif
6358
6359 EXIT();
6360 return 0;
6361}
6362
Rajeev Kumar98edb772016-01-19 12:42:19 -08006363/**
6364 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6365 * @wiphy: Pointer to the wiphy structure
6366 * @ndev: Pointer to the net device
6367 * @type: Interface type
6368 * @flags: Flags for change interface
6369 * @params: Pointer to change interface parameters
6370 *
6371 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006372 */
6373static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6374 struct net_device *ndev,
6375 enum nl80211_iftype type,
6376 u32 *flags,
6377 struct vif_params *params)
6378{
6379 int ret;
6380
6381 cds_ssr_protect(__func__);
6382 ret =
6383 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
6384 cds_ssr_unprotect(__func__);
6385
6386 return ret;
6387}
6388
6389#ifdef FEATURE_WLAN_TDLS
6390static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
6391 int index, uint8_t match)
6392{
6393 int i;
6394 for (i = 0; i < index; i++) {
6395 if (arr[i] == match)
6396 return true;
6397 }
6398 return false;
6399}
6400#endif
6401
6402/**
6403 * __wlan_hdd_change_station() - change station
6404 * @wiphy: Pointer to the wiphy structure
6405 * @dev: Pointer to the net device.
6406 * @mac: bssid
6407 * @params: Pointer to station parameters
6408 *
6409 * Return: 0 for success, error number on failure.
6410 */
6411#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6412static int __wlan_hdd_change_station(struct wiphy *wiphy,
6413 struct net_device *dev,
6414 const uint8_t *mac,
6415 struct station_parameters *params)
6416#else
6417static int __wlan_hdd_change_station(struct wiphy *wiphy,
6418 struct net_device *dev,
6419 uint8_t *mac,
6420 struct station_parameters *params)
6421#endif
6422{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306423 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006424 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6425 hdd_context_t *pHddCtx;
6426 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05306427 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006428#ifdef FEATURE_WLAN_TDLS
6429 tCsrStaParams StaParams = { 0 };
6430 uint8_t isBufSta = 0;
6431 uint8_t isOffChannelSupported = 0;
6432#endif
6433 int ret;
6434
6435 ENTER();
6436
Anurag Chouhan6d760662016-02-20 16:05:43 +05306437 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006438 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6439 return -EINVAL;
6440 }
6441
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306442 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006443 TRACE_CODE_HDD_CHANGE_STATION,
6444 pAdapter->sessionId, params->listen_interval));
6445
6446 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6447 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306448 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006449 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006450
6451 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6452
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306453 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006454
Krunal Sonib4326f22016-03-10 13:05:51 -08006455 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
6456 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006457 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
6458 status =
6459 hdd_softap_change_sta_state(pAdapter,
6460 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08006461 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006462
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306463 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306464 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006465 FL
6466 ("Not able to change TL state to AUTHENTICATED"));
6467 return -EINVAL;
6468 }
6469 }
Krunal Sonib4326f22016-03-10 13:05:51 -08006470 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
6471 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006472#ifdef FEATURE_WLAN_TDLS
6473 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
6474 StaParams.capability = params->capability;
6475 StaParams.uapsd_queues = params->uapsd_queues;
6476 StaParams.max_sp = params->max_sp;
6477
6478 /* Convert (first channel , number of channels) tuple to
6479 * the total list of channels. This goes with the assumption
6480 * that if the first channel is < 14, then the next channels
6481 * are an incremental of 1 else an incremental of 4 till the number
6482 * of channels.
6483 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306484 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006485 "%s: params->supported_channels_len: %d",
6486 __func__, params->supported_channels_len);
6487 if (0 != params->supported_channels_len) {
6488 int i = 0, j = 0, k = 0, no_of_channels = 0;
6489 int num_unique_channels;
6490 int next;
6491 for (i = 0;
6492 i < params->supported_channels_len
6493 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
6494 int wifi_chan_index;
6495 if (!wlan_hdd_is_duplicate_channel
6496 (StaParams.supported_channels, j,
6497 params->supported_channels[i])) {
6498 StaParams.
6499 supported_channels[j] =
6500 params->
6501 supported_channels[i];
6502 } else {
6503 continue;
6504 }
6505 wifi_chan_index =
6506 ((StaParams.supported_channels[j] <=
6507 HDD_CHANNEL_14) ? 1 : 4);
6508 no_of_channels =
6509 params->supported_channels[i + 1];
6510
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306511 QDF_TRACE(QDF_MODULE_ID_HDD,
6512 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006513 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d",
6514 __func__, i, j, k, j,
6515 StaParams.
6516 supported_channels[j],
6517 wifi_chan_index,
6518 no_of_channels);
6519 for (k = 1; k <= no_of_channels &&
6520 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
6521 k++) {
6522 next =
6523 StaParams.
6524 supported_channels[j] +
6525 wifi_chan_index;
6526 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
6527 StaParams.
6528 supported_channels[j
6529 +
6530 1]
6531 = next;
6532 } else {
6533 continue;
6534 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306535 QDF_TRACE(QDF_MODULE_ID_HDD,
6536 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006537 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d",
6538 __func__, i, j, k,
6539 j + 1,
6540 StaParams.
6541 supported_channels[j +
6542 1]);
6543 j += 1;
6544 }
6545 }
6546 num_unique_channels = j + 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306547 QDF_TRACE(QDF_MODULE_ID_HDD,
6548 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006549 "%s: Unique Channel List", __func__);
6550 for (i = 0; i < num_unique_channels; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306551 QDF_TRACE(QDF_MODULE_ID_HDD,
6552 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006553 "%s: StaParams.supported_channels[%d]: %d,",
6554 __func__, i,
6555 StaParams.
6556 supported_channels[i]);
6557 }
6558 if (MAX_CHANNEL < num_unique_channels)
6559 num_unique_channels = MAX_CHANNEL;
6560 StaParams.supported_channels_len =
6561 num_unique_channels;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306562 QDF_TRACE(QDF_MODULE_ID_HDD,
6563 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006564 "%s: After removing duplcates StaParams.supported_channels_len: %d",
6565 __func__,
6566 StaParams.supported_channels_len);
6567 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306568 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006569 params->supported_oper_classes,
6570 params->supported_oper_classes_len);
6571 StaParams.supported_oper_classes_len =
6572 params->supported_oper_classes_len;
6573
6574 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306575 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006576 params->ext_capab,
6577 sizeof(StaParams.extn_capability));
6578
6579 if (NULL != params->ht_capa) {
6580 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306581 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006582 sizeof(tSirHTCap));
6583 }
6584
6585 StaParams.supported_rates_len =
6586 params->supported_rates_len;
6587
6588 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
6589 * The supported_rates array , for all the structures propogating till Add Sta
6590 * to the firmware has to be modified , if the supplicant (ieee80211) is
6591 * modified to send more rates.
6592 */
6593
6594 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
6595 */
6596 if (StaParams.supported_rates_len >
6597 SIR_MAC_MAX_SUPP_RATES)
6598 StaParams.supported_rates_len =
6599 SIR_MAC_MAX_SUPP_RATES;
6600
6601 if (0 != StaParams.supported_rates_len) {
6602 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306603 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006604 params->supported_rates,
6605 StaParams.supported_rates_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306606 QDF_TRACE(QDF_MODULE_ID_HDD,
6607 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006608 "Supported Rates with Length %d",
6609 StaParams.supported_rates_len);
6610 for (i = 0; i < StaParams.supported_rates_len;
6611 i++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306612 QDF_TRACE(QDF_MODULE_ID_HDD,
6613 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006614 "[%d]: %0x", i,
6615 StaParams.supported_rates[i]);
6616 }
6617
6618 if (NULL != params->vht_capa) {
6619 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306620 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006621 params->vht_capa,
6622 sizeof(tSirVHTCap));
6623 }
6624
6625 if (0 != params->ext_capab_len) {
6626 /*Define A Macro : TODO Sunil */
6627 if ((1 << 4) & StaParams.extn_capability[3]) {
6628 isBufSta = 1;
6629 }
6630 /* TDLS Channel Switching Support */
6631 if ((1 << 6) & StaParams.extn_capability[3]) {
6632 isOffChannelSupported = 1;
6633 }
6634 }
6635
6636 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
6637 &StaParams,
6638 isBufSta,
6639 isOffChannelSupported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306640 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306641 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006642 FL
6643 ("wlan_hdd_tdls_set_peer_caps failed!"));
6644 return -EINVAL;
6645 }
6646
6647 status =
6648 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
6649 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306650 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306651 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006652 FL("wlan_hdd_tdls_add_station failed!"));
6653 return -EINVAL;
6654 }
6655 }
6656#endif
6657 }
6658 EXIT();
6659 return ret;
6660}
6661
6662/**
6663 * wlan_hdd_change_station() - cfg80211 change station handler function
6664 * @wiphy: Pointer to the wiphy structure
6665 * @dev: Pointer to the net device.
6666 * @mac: bssid
6667 * @params: Pointer to station parameters
6668 *
6669 * This is the cfg80211 change station handler function which invokes
6670 * the internal function @__wlan_hdd_change_station with
6671 * SSR protection.
6672 *
6673 * Return: 0 for success, error number on failure.
6674 */
6675#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
6676static int wlan_hdd_change_station(struct wiphy *wiphy,
6677 struct net_device *dev,
6678 const u8 *mac,
6679 struct station_parameters *params)
6680#else
6681static int wlan_hdd_change_station(struct wiphy *wiphy,
6682 struct net_device *dev,
6683 u8 *mac,
6684 struct station_parameters *params)
6685#endif
6686{
6687 int ret;
6688
6689 cds_ssr_protect(__func__);
6690 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
6691 cds_ssr_unprotect(__func__);
6692
6693 return ret;
6694}
6695
6696/*
6697 * FUNCTION: __wlan_hdd_cfg80211_add_key
6698 * This function is used to initialize the key information
6699 */
6700static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6701 struct net_device *ndev,
6702 u8 key_index, bool pairwise,
6703 const u8 *mac_addr,
6704 struct key_params *params)
6705{
6706 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6707 tCsrRoamSetKey setKey;
6708 int status;
6709 uint32_t roamId = 0xFF;
6710#ifndef WLAN_FEATURE_MBSSID
6711 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context;
6712#endif
6713 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306714 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006715 hdd_context_t *pHddCtx;
6716 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6717
6718 ENTER();
6719
Anurag Chouhan6d760662016-02-20 16:05:43 +05306720 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006721 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6722 return -EINVAL;
6723 }
6724
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306725 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006726 TRACE_CODE_HDD_CFG80211_ADD_KEY,
6727 pAdapter->sessionId, params->key_len));
6728 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6729 status = wlan_hdd_validate_context(pHddCtx);
6730
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306731 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006732 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006733
6734 hddLog(LOG1, FL("Device_mode %s(%d)"),
6735 hdd_device_mode_to_string(pAdapter->device_mode),
6736 pAdapter->device_mode);
6737
6738 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306739 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 __func__, key_index);
6741
6742 return -EINVAL;
6743 }
6744
6745 if (CSR_MAX_KEY_LEN < params->key_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306746 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006747 __func__, params->key_len);
6748
6749 return -EINVAL;
6750 }
6751
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306752 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006753 "%s: called with key index = %d & key length %d",
6754 __func__, key_index, params->key_len);
6755
6756 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306757 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006758 setKey.keyId = key_index;
6759 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306760 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006761
6762 switch (params->cipher) {
6763 case WLAN_CIPHER_SUITE_WEP40:
6764 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6765 break;
6766
6767 case WLAN_CIPHER_SUITE_WEP104:
6768 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
6769 break;
6770
6771 case WLAN_CIPHER_SUITE_TKIP:
6772 {
6773 u8 *pKey = &setKey.Key[0];
6774 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
6775
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306776 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006777
6778 /*Supplicant sends the 32bytes key in this order
6779
6780 |--------------|----------|----------|
6781 | Tk1 |TX-MIC | RX Mic |
6782 |||--------------|----------|----------|
6783 <---16bytes---><--8bytes--><--8bytes-->
6784
6785 */
6786 /*Sme expects the 32 bytes key to be in the below order
6787
6788 |--------------|----------|----------|
6789 | Tk1 |RX-MIC | TX Mic |
6790 |||--------------|----------|----------|
6791 <---16bytes---><--8bytes--><--8bytes-->
6792 */
6793 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306794 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006795
6796 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306797 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006798
6799 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306800 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006801
6802 break;
6803 }
6804
6805 case WLAN_CIPHER_SUITE_CCMP:
6806 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
6807 break;
6808
6809#ifdef FEATURE_WLAN_WAPI
6810 case WLAN_CIPHER_SUITE_SMS4:
6811 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306812 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006813 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
6814 mac_addr, params->key,
6815 params->key_len);
6816 return 0;
6817 }
6818#endif
6819
6820#ifdef FEATURE_WLAN_ESE
6821 case WLAN_CIPHER_SUITE_KRK:
6822 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
6823 break;
6824#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6825 case WLAN_CIPHER_SUITE_BTK:
6826 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
6827 break;
6828#endif
6829#endif
6830
6831#ifdef WLAN_FEATURE_11W
6832 case WLAN_CIPHER_SUITE_AES_CMAC:
6833 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
6834 break;
6835#endif
6836
6837 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306838 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006839 __func__, params->cipher);
6840 return -EOPNOTSUPP;
6841 }
6842
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306843 hddLog(QDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006844 __func__, setKey.encType);
6845
6846 if (!pairwise) {
6847 /* set group key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306848 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006849 "%s- %d: setting Broadcast key", __func__, __LINE__);
6850 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05306851 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006852 } else {
6853 /* set pairwise key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306854 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006855 "%s- %d: setting pairwise key", __func__, __LINE__);
6856 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306857 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006858 }
Krunal Sonib4326f22016-03-10 13:05:51 -08006859 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006860 /* if a key is already installed, block all subsequent ones */
6861 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306862 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006863 "%s: IBSS key installed already", __func__);
6864 return 0;
6865 }
6866
6867 setKey.keyDirection = eSIR_TX_RX;
6868 /*Set the group key */
6869 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6870 pAdapter->sessionId, &setKey, &roamId);
6871
6872 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306873 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006874 "%s: sme_roam_set_key failed, returned %d",
6875 __func__, status);
6876 return -EINVAL;
6877 }
6878 /*Save the keys here and call sme_roam_set_key for setting
6879 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306880 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006881 &setKey, sizeof(tCsrRoamSetKey));
6882
6883 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
6884 return status;
6885 }
Krunal Sonib4326f22016-03-10 13:05:51 -08006886 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
6887 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006888 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6889 if (pHostapdState->bssState == BSS_START) {
6890#ifdef WLAN_FEATURE_MBSSID
6891 status =
6892 wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR
6893 (pAdapter), &setKey);
6894#else
6895 status = wlansap_set_key_sta(p_cds_context, &setKey);
6896#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306897 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306898 QDF_TRACE(QDF_MODULE_ID_HDD,
6899 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006900 "[%4d] wlansap_set_key_sta returned ERROR status= %d",
6901 __LINE__, status);
6902 }
6903 }
6904
6905 /* Save the key in ap ctx for use on START_BASS and restart */
6906 if (pairwise ||
6907 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
6908 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306909 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006910 sizeof(tCsrRoamSetKey));
6911 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306912 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006913 sizeof(tCsrRoamSetKey));
6914
Krunal Sonib4326f22016-03-10 13:05:51 -08006915 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
6916 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006917 hdd_wext_state_t *pWextState =
6918 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6919 hdd_station_ctx_t *pHddStaCtx =
6920 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6921
6922 if (!pairwise) {
6923 /* set group key */
6924 if (pHddStaCtx->roam_info.deferKeyComplete) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306925 QDF_TRACE(QDF_MODULE_ID_HDD,
6926 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006927 "%s- %d: Perform Set key Complete",
6928 __func__, __LINE__);
6929 hdd_perform_roam_set_key_complete(pAdapter);
6930 }
6931 }
6932
6933 pWextState->roamProfile.Keys.KeyLength[key_index] =
6934 (u8) params->key_len;
6935
6936 pWextState->roamProfile.Keys.defaultIndex = key_index;
6937
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306938 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006939 KeyMaterial[key_index][0], params->key,
6940 params->key_len);
6941
6942 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6943
6944 hddLog(LOG2,
6945 FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"),
6946 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6947 setKey.keyDirection);
6948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006949 /* The supplicant may attempt to set the PTK once pre-authentication
6950 is done. Save the key in the UMAC and include it in the ADD BSS
6951 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306952 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006953 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306954 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306955 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006956 "%s: Update PreAuth Key success", __func__);
6957 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306958 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306959 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006960 "%s: Update PreAuth Key failed", __func__);
6961 return -EINVAL;
6962 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006963
6964 /* issue set key request to SME */
6965 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6966 pAdapter->sessionId, &setKey, &roamId);
6967
6968 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306969 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006970 "%s: sme_roam_set_key failed, returned %d",
6971 __func__, status);
6972 pHddStaCtx->roam_info.roamingState =
6973 HDD_ROAM_STATE_NONE;
6974 return -EINVAL;
6975 }
6976
6977 /* in case of IBSS as there was no information available about WEP keys during
6978 * IBSS join, group key intialized with NULL key, so re-initialize group key
6979 * with correct value*/
6980 if ((eCSR_BSS_TYPE_START_IBSS ==
6981 pWextState->roamProfile.BSSType)
6982 &&
6983 !((IW_AUTH_KEY_MGMT_802_1X ==
6984 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
6985 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
6986 pHddStaCtx->conn_info.authType)
6987 )
6988 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
6989 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
6990 )
6991 ) {
6992 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05306993 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006994
6995 hddLog(LOG2,
6996 FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"),
6997 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6998 setKey.keyDirection);
6999
7000 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7001 pAdapter->sessionId, &setKey,
7002 &roamId);
7003
7004 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307005 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007006 "%s: sme_roam_set_key failed for group key (IBSS), returned %d",
7007 __func__, status);
7008 pHddStaCtx->roam_info.roamingState =
7009 HDD_ROAM_STATE_NONE;
7010 return -EINVAL;
7011 }
7012 }
7013 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307014 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007015 return 0;
7016}
7017
7018static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
7019 struct net_device *ndev,
7020 u8 key_index, bool pairwise,
7021 const u8 *mac_addr,
7022 struct key_params *params)
7023{
7024 int ret;
7025 cds_ssr_protect(__func__);
7026 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
7027 mac_addr, params);
7028 cds_ssr_unprotect(__func__);
7029
7030 return ret;
7031}
7032
7033/*
7034 * FUNCTION: __wlan_hdd_cfg80211_get_key
7035 * This function is used to get the key information
7036 */
7037static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7038 struct net_device *ndev,
7039 u8 key_index, bool pairwise,
7040 const u8 *mac_addr, void *cookie,
7041 void (*callback)(void *cookie,
7042 struct key_params *)
7043 )
7044{
7045 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7046 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7047 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
7048 struct key_params params;
7049
7050 ENTER();
7051
Anurag Chouhan6d760662016-02-20 16:05:43 +05307052 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007053 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7054 return -EINVAL;
7055 }
7056
7057 hddLog(LOG1, FL("Device_mode %s(%d)"),
7058 hdd_device_mode_to_string(pAdapter->device_mode),
7059 pAdapter->device_mode);
7060
7061 memset(&params, 0, sizeof(params));
7062
7063 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307064 hddLog(QDF_TRACE_LEVEL_ERROR, FL("invalid key index %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007065 key_index);
7066 return -EINVAL;
7067 }
7068
7069 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
7070 case eCSR_ENCRYPT_TYPE_NONE:
7071 params.cipher = IW_AUTH_CIPHER_NONE;
7072 break;
7073
7074 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
7075 case eCSR_ENCRYPT_TYPE_WEP40:
7076 params.cipher = WLAN_CIPHER_SUITE_WEP40;
7077 break;
7078
7079 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
7080 case eCSR_ENCRYPT_TYPE_WEP104:
7081 params.cipher = WLAN_CIPHER_SUITE_WEP104;
7082 break;
7083
7084 case eCSR_ENCRYPT_TYPE_TKIP:
7085 params.cipher = WLAN_CIPHER_SUITE_TKIP;
7086 break;
7087
7088 case eCSR_ENCRYPT_TYPE_AES:
7089 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
7090 break;
7091
7092 default:
7093 params.cipher = IW_AUTH_CIPHER_NONE;
7094 break;
7095 }
7096
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307097 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007098 TRACE_CODE_HDD_CFG80211_GET_KEY,
7099 pAdapter->sessionId, params.cipher));
7100
7101 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
7102 params.seq_len = 0;
7103 params.seq = NULL;
7104 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
7105 callback(cookie, &params);
7106
7107 EXIT();
7108 return 0;
7109}
7110
7111static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7112 struct net_device *ndev,
7113 u8 key_index, bool pairwise,
7114 const u8 *mac_addr, void *cookie,
7115 void (*callback)(void *cookie,
7116 struct key_params *)
7117 )
7118{
7119 int ret;
7120
7121 cds_ssr_protect(__func__);
7122 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
7123 mac_addr, cookie, callback);
7124 cds_ssr_unprotect(__func__);
7125
7126 return ret;
7127}
7128
7129/**
7130 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
7131 * @wiphy: wiphy interface context
7132 * @ndev: pointer to net device
7133 * @key_index: Key index used in 802.11 frames
7134 * @unicast: true if it is unicast key
7135 * @multicast: true if it is multicast key
7136 *
7137 * This function is required for cfg80211_ops API.
7138 * It is used to delete the key information
7139 * Underlying hardware implementation does not have API to delete the
7140 * encryption key. It is automatically deleted when the peer is
7141 * removed. Hence this function currently does nothing.
7142 * Future implementation may interprete delete key operation to
7143 * replacing the key with a random junk value, effectively making it
7144 * useless.
7145 *
7146 * Return: status code, always 0.
7147 */
7148
7149static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7150 struct net_device *ndev,
7151 u8 key_index,
7152 bool pairwise, const u8 *mac_addr)
7153{
7154 EXIT();
7155 return 0;
7156}
7157
7158/**
7159 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
7160 * @wiphy: Pointer to wiphy structure.
7161 * @dev: Pointer to net_device structure.
7162 * @key_index: key index
7163 * @pairwise: pairwise
7164 * @mac_addr: mac address
7165 *
7166 * This is the cfg80211 delete key handler function which invokes
7167 * the internal function @__wlan_hdd_cfg80211_del_key with
7168 * SSR protection.
7169 *
7170 * Return: 0 for success, error number on failure.
7171 */
7172static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7173 struct net_device *dev,
7174 u8 key_index,
7175 bool pairwise, const u8 *mac_addr)
7176{
7177 int ret;
7178
7179 cds_ssr_protect(__func__);
7180 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
7181 pairwise, mac_addr);
7182 cds_ssr_unprotect(__func__);
7183
7184 return ret;
7185}
7186
7187/*
7188 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
7189 * This function is used to set the default tx key index
7190 */
7191static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7192 struct net_device *ndev,
7193 u8 key_index,
7194 bool unicast, bool multicast)
7195{
7196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7197 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7198 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7199 hdd_context_t *pHddCtx;
7200 int status;
7201
7202 ENTER();
7203
Anurag Chouhan6d760662016-02-20 16:05:43 +05307204 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007205 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7206 return -EINVAL;
7207 }
7208
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307209 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007210 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
7211 pAdapter->sessionId, key_index));
7212
7213 hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"),
7214 hdd_device_mode_to_string(pAdapter->device_mode),
7215 pAdapter->device_mode, key_index);
7216
7217 if (CSR_MAX_NUM_KEY <= key_index) {
7218 hddLog(LOGE, FL("Invalid key index %d"), key_index);
7219 return -EINVAL;
7220 }
7221
7222 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7223 status = wlan_hdd_validate_context(pHddCtx);
7224
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307225 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007226 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007227
Krunal Sonib4326f22016-03-10 13:05:51 -08007228 if ((pAdapter->device_mode == QDF_STA_MODE) ||
7229 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007230 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7231 pHddStaCtx->conn_info.ucEncryptionType) &&
7232 (eCSR_ENCRYPT_TYPE_AES !=
7233 pHddStaCtx->conn_info.ucEncryptionType)) {
7234 /* If default key index is not same as previous one,
7235 * then update the default key index */
7236
7237 tCsrRoamSetKey setKey;
7238 uint32_t roamId = 0xFF;
7239 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
7240
7241 hddLog(LOG2, FL("Default tx key index %d"), key_index);
7242
7243 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307244 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007245 setKey.keyId = key_index;
7246 setKey.keyLength = Keys->KeyLength[key_index];
7247
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307248 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007249 &Keys->KeyMaterial[key_index][0],
7250 Keys->KeyLength[key_index]);
7251
7252 setKey.keyDirection = eSIR_TX_RX;
7253
Anurag Chouhanc5548422016-02-24 18:33:27 +05307254 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007255 &pHddStaCtx->conn_info.bssId);
7256
7257 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
7258 pWextState->roamProfile.EncryptionType.
7259 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
7260 /* In the case of dynamic wep supplicant hardcodes DWEP type
7261 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
7262 * WEP-40 encryption. In this canse the key length is 5 but the
7263 * encryption type is 104 hence checking the key langht(5) and
7264 * encryption type(104) and switching encryption type to 40*/
7265 pWextState->roamProfile.EncryptionType.
7266 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7267 pWextState->roamProfile.mcEncryptionType.
7268 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7269 }
7270
7271 setKey.encType =
7272 pWextState->roamProfile.EncryptionType.
7273 encryptionType[0];
7274
7275 /* Issue set key request */
7276 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7277 pAdapter->sessionId, &setKey,
7278 &roamId);
7279
7280 if (0 != status) {
7281 hddLog(LOGE,
7282 FL("sme_roam_set_key failed, returned %d"),
7283 status);
7284 return -EINVAL;
7285 }
7286 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007287 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007288 /* In SoftAp mode setting key direction for default mode */
7289 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7290 pWextState->roamProfile.EncryptionType.encryptionType[0])
7291 && (eCSR_ENCRYPT_TYPE_AES !=
7292 pWextState->roamProfile.EncryptionType.
7293 encryptionType[0])) {
7294 /* Saving key direction for default key index to TX default */
7295 hdd_ap_ctx_t *pAPCtx =
7296 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7297 pAPCtx->wepKey[key_index].keyDirection =
7298 eSIR_TX_DEFAULT;
7299 }
7300 }
7301
7302 EXIT();
7303 return status;
7304}
7305
7306static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7307 struct net_device *ndev,
7308 u8 key_index,
7309 bool unicast, bool multicast)
7310{
7311 int ret;
7312 cds_ssr_protect(__func__);
7313 ret =
7314 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
7315 multicast);
7316 cds_ssr_unprotect(__func__);
7317
7318 return ret;
7319}
7320
7321/**
7322 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
7323 * @pAdapter: Pointer to adapter
7324 * @pRoamInfo: Pointer to roam info
7325 *
7326 * Return: struct cfg80211_bss pointer
7327 */
7328struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
7329 tCsrRoamInfo *pRoamInfo)
7330{
7331 struct net_device *dev = pAdapter->dev;
7332 struct wireless_dev *wdev = dev->ieee80211_ptr;
7333 struct wiphy *wiphy = wdev->wiphy;
7334 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
7335 int chan_no;
7336 unsigned int freq;
7337 struct ieee80211_channel *chan;
7338 struct cfg80211_bss *bss = NULL;
7339
7340 ENTER();
7341
7342 if (NULL == pBssDesc) {
7343 hddLog(LOGE, FL("pBssDesc is NULL"));
7344 return bss;
7345 }
7346
7347 if (NULL == pRoamInfo->pProfile) {
7348 hddLog(LOGE, FL("Roam profile is NULL"));
7349 return bss;
7350 }
7351
7352 chan_no = pBssDesc->channelId;
7353
7354 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
7355 freq =
7356 ieee80211_channel_to_frequency(chan_no,
7357 IEEE80211_BAND_2GHZ);
7358 } else {
7359 freq =
7360 ieee80211_channel_to_frequency(chan_no,
7361 IEEE80211_BAND_5GHZ);
7362 }
7363
7364 chan = __ieee80211_get_channel(wiphy, freq);
7365
7366 if (!chan) {
7367 hddLog(LOGE, FL("chan pointer is NULL"));
7368 return NULL;
7369 }
7370
7371 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
7372 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
7373 ssId[0],
7374 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
Ryan Hsu535d16a2016-01-18 16:45:12 -08007375#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007376 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
Ryan Hsu535d16a2016-01-18 16:45:12 -08007377#else
7378 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
7379#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007380 if (bss == NULL) {
7381 hddLog(LOGE, FL("BSS not present"));
7382 } else {
7383 hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID "
7384 MAC_ADDRESS_STR),
7385 MAC_ADDR_ARRAY(pBssDesc->bssId));
7386 cfg80211_unlink_bss(wiphy, bss);
7387 }
7388 return bss;
7389}
7390
7391/**
7392 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
7393 * @pAdapter: Pointer to adapter
7394 * @bss_desc: Pointer to bss descriptor
7395 *
7396 * This function is used to inform the BSS details to nl80211 interface.
7397 *
7398 * Return: struct cfg80211_bss pointer
7399 */
7400static struct cfg80211_bss *
7401wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
7402 tSirBssDescription *bss_desc)
7403{
7404 /*
7405 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
7406 * already exists in bss data base of cfg80211 for that particular BSS
7407 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
7408 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
7409 * As of now there is no possibility to get the mgmt(probe response)
7410 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
7411 * and passing to cfg80211_inform_bss_frame.
7412 */
7413 struct net_device *dev = pAdapter->dev;
7414 struct wireless_dev *wdev = dev->ieee80211_ptr;
7415 struct wiphy *wiphy = wdev->wiphy;
7416 int chan_no = bss_desc->channelId;
7417#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7418 qcom_ie_age *qie_age = NULL;
7419 int ie_length =
7420 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
7421#else
7422 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
7423#endif
7424 const char *ie =
7425 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
7426 unsigned int freq;
7427 struct ieee80211_channel *chan;
7428 struct ieee80211_mgmt *mgmt = NULL;
7429 struct cfg80211_bss *bss_status = NULL;
7430 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
7431 int rssi = 0;
7432 hdd_context_t *pHddCtx;
7433 int status;
7434#ifdef CONFIG_CNSS
7435 struct timespec ts;
7436#endif
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007437 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007438
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307439 ENTER();
7440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007441 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7442 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307443 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007444 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007445
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007446 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007447 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
7448 if (!mgmt) {
7449 hddLog(LOGE, FL("memory allocation failed"));
7450 return NULL;
7451 }
7452
7453 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
7454
7455#ifdef CONFIG_CNSS
7456 /* Android does not want the timestamp from the frame.
7457 Instead it wants a monotonic increasing value */
7458 cnss_get_monotonic_boottime(&ts);
7459 mgmt->u.probe_resp.timestamp =
7460 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
7461#else
7462 /* keep old behavior for non-open source (for now) */
7463 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
7464 sizeof(bss_desc->timeStamp));
7465
7466#endif
7467
7468 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
7469 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
7470
7471#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
7472 /* GPS Requirement: need age ie per entry. Using vendor specific. */
7473 /* Assuming this is the last IE, copy at the end */
7474 ie_length -= sizeof(qcom_ie_age);
7475 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
7476 qie_age->element_id = QCOM_VENDOR_IE_ID;
7477 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
7478 qie_age->oui_1 = QCOM_OUI1;
7479 qie_age->oui_2 = QCOM_OUI2;
7480 qie_age->oui_3 = QCOM_OUI3;
7481 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
7482 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +05307483 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007484 qie_age->tsf_delta = bss_desc->tsf_delta;
7485#endif
7486
7487 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
7488 if (bss_desc->fProbeRsp) {
7489 mgmt->frame_control |=
7490 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
7491 } else {
7492 mgmt->frame_control |=
7493 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
7494 }
7495
7496 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
7497 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
7498 freq =
7499 ieee80211_channel_to_frequency(chan_no,
7500 IEEE80211_BAND_2GHZ);
7501 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
7502 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
7503 freq =
7504 ieee80211_channel_to_frequency(chan_no,
7505 IEEE80211_BAND_5GHZ);
7506 } else {
7507 hddLog(LOGE, FL("Invalid chan_no %d"), chan_no);
7508 kfree(mgmt);
7509 return NULL;
7510 }
7511
7512 chan = __ieee80211_get_channel(wiphy, freq);
7513 /* When the band is changed on the fly using the GUI, three things are done
7514 * 1. scan abort
7515 * 2. flush scan results from cache
7516 * 3. update the band with the new band user specified (refer to the
7517 * hdd_set_band_helper function) as part of the scan abort, message will be
7518 * queued to PE and we proceed with flushing and changinh the band.
7519 * PE will stop the scanning further and report back the results what ever
7520 * it had till now by calling the call back function.
7521 * if the time between update band and scandone call back is sufficient
7522 * enough the band change reflects in SME, SME validates the channels
7523 * and discards the channels correponding to previous band and calls back
7524 * with zero bss results. but if the time between band update and scan done
7525 * callback is very small then band change will not reflect in SME and SME
7526 * reports to HDD all the channels correponding to previous band.this is due
7527 * to race condition.but those channels are invalid to the new band and so
7528 * this function __ieee80211_get_channel will return NULL.Each time we
7529 * report scan result with this pointer null warning kernel trace is printed.
7530 * if the scan results contain large number of APs continuosly kernel
7531 * warning trace is printed and it will lead to apps watch dog bark.
7532 * So drop the bss and continue to next bss.
7533 */
7534 if (chan == NULL) {
7535 hddLog(LOGE, FL("chan pointer is NULL"));
7536 kfree(mgmt);
7537 return NULL;
7538 }
7539
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07007540 /* Based on .ini configuration, raw rssi can be reported for bss.
7541 * Raw rssi is typically used for estimating power.
7542 */
7543
7544 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
7545 bss_desc->rssi;
7546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007547 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +05307548 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007549
7550 hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"),
7551 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
7552 (int)(rssi / 100));
7553
7554 bss_status =
7555 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
7556 GFP_KERNEL);
7557 kfree(mgmt);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307558 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007559 return bss_status;
7560}
7561
7562/**
7563 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
7564 * @pAdapter: Pointer to adapter
7565 * @pRoamInfo: Pointer to roam info
7566 *
7567 * This function is used to update the BSS data base of CFG8011
7568 *
7569 * Return: struct cfg80211_bss pointer
7570 */
7571struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
7572 tCsrRoamInfo *pRoamInfo)
7573{
7574 tCsrRoamConnectedProfile roamProfile;
7575 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7576 struct cfg80211_bss *bss = NULL;
7577
7578 ENTER();
7579
7580 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
7581 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
7582
7583 if (NULL != roamProfile.pBssDesc) {
7584 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7585 roamProfile.pBssDesc);
7586
7587 if (NULL == bss)
7588 hddLog(LOG1,
7589 FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL"));
7590
Naveen Rawatdf0a7e72016-01-06 18:35:53 -08007591 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007592 } else {
7593 hddLog(LOGE, FL("roamProfile.pBssDesc is NULL"));
7594 }
7595 EXIT();
7596 return bss;
7597}
7598/**
7599 * wlan_hdd_cfg80211_update_bss() - update bss
7600 * @wiphy: Pointer to wiphy
7601 * @pAdapter: Pointer to adapter
7602 * @scan_time: scan request timestamp
7603 *
7604 * Return: zero if success, non-zero otherwise
7605 */
7606int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
7607 hdd_adapter_t *pAdapter,
7608 uint32_t scan_time)
7609{
7610 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
7611 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307612 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007613 tScanResultHandle pResult;
7614 struct cfg80211_bss *bss_status = NULL;
7615 hdd_context_t *pHddCtx;
7616 int ret;
7617
7618 ENTER();
7619
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307620 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007621 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
7622 NO_SESSION, pAdapter->sessionId));
7623
7624 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7625 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307626 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007627 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007628
7629 /* start getting scan results and populate cgf80211 BSS database */
7630 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
7631
7632 /* no scan results */
7633 if (NULL == pResult) {
7634 hddLog(LOGE, FL("No scan result Status %d"), status);
7635 return status;
7636 }
7637
7638 pScanResult = sme_scan_result_get_first(hHal, pResult);
7639
7640 while (pScanResult) {
7641 /*
7642 * - cfg80211_inform_bss() is not updating ie field of bss
7643 * entry if entry already exists in bss data base of cfg80211
7644 * for that particular BSS ID. Using cfg80211_inform_bss_frame
7645 * to update thebss entry instead of cfg80211_inform_bss,
7646 * But this call expects mgmt packet as input. As of now
7647 * there is no possibility to get the mgmt(probe response)
7648 * frame from PE, converting bss_desc to
7649 * ieee80211_mgmt(probe response) and passing to c
7650 * fg80211_inform_bss_frame.
7651 * - Update BSS only if beacon timestamp is later than
7652 * scan request timestamp.
7653 */
7654 if ((scan_time == 0) ||
7655 (scan_time <
7656 pScanResult->BssDescriptor.nReceivedTime)) {
7657 bss_status =
7658 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7659 &pScanResult->BssDescriptor);
7660
7661 if (NULL == bss_status) {
7662 hdd_info("NULL returned by cfg80211_inform_bss_frame");
7663 } else {
7664 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007665 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007666 bss_status);
7667 }
7668 } else {
7669 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
7670 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
7671 }
7672 pScanResult = sme_scan_result_get_next(hHal, pResult);
7673 }
7674
7675 sme_scan_result_purge(hHal, pResult);
7676 /*
7677 * For SAP mode, scan is invoked by hostapd during SAP start
7678 * if hostapd is restarted, we need to flush previous scan
7679 * result so that it will reflect environment change
7680 */
Krunal Sonib4326f22016-03-10 13:05:51 -08007681 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007682#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
7683 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
7684#endif
7685 )
7686 sme_scan_flush_result(hHal);
7687
7688 EXIT();
7689 return 0;
7690}
7691
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007692/**
7693 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
7694 * @pAdapter: Pointer to adapter
7695 * @pRoamInfo: Pointer to roam info
7696 * @index: Index
7697 * @preauth: Preauth flag
7698 *
7699 * This function is used to notify the supplicant of a new PMKSA candidate.
7700 *
7701 * Return: 0 for success, non-zero for failure
7702 */
7703int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
7704 tCsrRoamInfo *pRoamInfo,
7705 int index, bool preauth)
7706{
7707#ifdef FEATURE_WLAN_OKC
7708 struct net_device *dev = pAdapter->dev;
7709 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
7710
7711 ENTER();
7712 hddLog(LOG1, FL("is going to notify supplicant of:"));
7713
7714 if (NULL == pRoamInfo) {
7715 hddLog(LOGP, FL("pRoamInfo is NULL"));
7716 return -EINVAL;
7717 }
7718
7719 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
7720 hddLog(LOG1, MAC_ADDRESS_STR,
7721 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
7722 cfg80211_pmksa_candidate_notify(dev, index,
7723 pRoamInfo->bssid.bytes,
7724 preauth, GFP_KERNEL);
7725 }
7726#endif /* FEATURE_WLAN_OKC */
7727 return 0;
7728}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007729
7730#ifdef FEATURE_WLAN_LFR_METRICS
7731/**
7732 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
7733 * @pAdapter: Pointer to adapter
7734 * @pRoamInfo: Pointer to roam info
7735 *
7736 * 802.11r/LFR metrics reporting function to report preauth initiation
7737 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307738 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007739 */
7740#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307741QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007742 tCsrRoamInfo *pRoamInfo)
7743{
7744 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7745 union iwreq_data wrqu;
7746
7747 ENTER();
7748
7749 if (NULL == pAdapter) {
7750 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307751 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007752 }
7753
7754 /* create the event */
7755 memset(&wrqu, 0, sizeof(wrqu));
7756 memset(metrics_notification, 0, sizeof(metrics_notification));
7757
7758 wrqu.data.pointer = metrics_notification;
7759 wrqu.data.length = scnprintf(metrics_notification,
7760 sizeof(metrics_notification),
7761 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
7762 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7763
7764 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7765 metrics_notification);
7766
7767 EXIT();
7768
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307769 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007770}
7771
7772/**
7773 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7774 * @pAdapter: Pointer to adapter
7775 * @pRoamInfo: Pointer to roam info
7776 * @preauth_status: Preauth status
7777 *
7778 * 802.11r/LFR metrics reporting function to report handover initiation
7779 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307780 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007781 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307782QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007783wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
7784 tCsrRoamInfo *pRoamInfo,
7785 bool preauth_status)
7786{
7787 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7788 union iwreq_data wrqu;
7789
7790 ENTER();
7791
7792 if (NULL == pAdapter) {
7793 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307794 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007795 }
7796
7797 /* create the event */
7798 memset(&wrqu, 0, sizeof(wrqu));
7799 memset(metrics_notification, 0, sizeof(metrics_notification));
7800
7801 scnprintf(metrics_notification, sizeof(metrics_notification),
7802 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
7803 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7804
7805 if (1 == preauth_status)
7806 strlcat(metrics_notification, " true",
7807 sizeof(metrics_notification));
7808 else
7809 strlcat(metrics_notification, " false",
7810 sizeof(metrics_notification));
7811
7812 wrqu.data.pointer = metrics_notification;
7813 wrqu.data.length = strlen(metrics_notification);
7814
7815 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7816 metrics_notification);
7817
7818 EXIT();
7819
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307820 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007821}
7822
7823/**
7824 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7825 * @pAdapter: Pointer to adapter
7826 * @pRoamInfo: Pointer to roam info
7827 *
7828 * 802.11r/LFR metrics reporting function to report handover initiation
7829 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307830 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007831 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307832QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007833 tCsrRoamInfo *pRoamInfo)
7834{
7835 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7836 union iwreq_data wrqu;
7837
7838 ENTER();
7839
7840 if (NULL == pAdapter) {
7841 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307842 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007843 }
7844
7845 /* create the event */
7846 memset(&wrqu, 0, sizeof(wrqu));
7847 memset(metrics_notification, 0, sizeof(metrics_notification));
7848
7849 wrqu.data.pointer = metrics_notification;
7850 wrqu.data.length = scnprintf(metrics_notification,
7851 sizeof(metrics_notification),
7852 "QCOM: LFR_PREAUTH_HANDOVER "
7853 MAC_ADDRESS_STR,
7854 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7855
7856 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7857 metrics_notification);
7858
7859 EXIT();
7860
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307861 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007862}
7863#endif
7864
7865/**
7866 * hdd_select_cbmode() - select channel bonding mode
7867 * @pAdapter: Pointer to adapter
7868 * @operatingChannel: Operating channel
7869 *
7870 * Return: none
7871 */
7872void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel)
7873{
7874 uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
7875 eHddDot11Mode hddDot11Mode = iniDot11Mode;
Amar Singhale4f28ee2015-10-21 14:36:56 -07007876 struct ch_params_s ch_params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007877 ch_params.ch_width =
7878 (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth;
7879
7880 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode);
7881 switch (iniDot11Mode) {
7882 case eHDD_DOT11_MODE_AUTO:
7883 case eHDD_DOT11_MODE_11ac:
7884 case eHDD_DOT11_MODE_11ac_ONLY:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007885 if (sme_is_feature_supported_by_fw(DOT11AC))
7886 hddDot11Mode = eHDD_DOT11_MODE_11ac;
7887 else
7888 hddDot11Mode = eHDD_DOT11_MODE_11n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007889 break;
7890 case eHDD_DOT11_MODE_11n:
7891 case eHDD_DOT11_MODE_11n_ONLY:
7892 hddDot11Mode = eHDD_DOT11_MODE_11n;
7893 break;
7894 default:
7895 hddDot11Mode = iniDot11Mode;
7896 break;
7897 }
7898 /* This call decides required channel bonding mode */
7899 sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal),
7900 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
7901 operationChannel, 0,
7902 &ch_params);
7903}
7904
7905
7906/*
7907 * FUNCTION: wlan_hdd_cfg80211_connect_start
7908 * wlan_hdd_cfg80211_connect_start() - start connection
7909 * @pAdapter: Pointer to adapter
7910 * @ssid: Pointer ot ssid
7911 * @ssid_len: Length of ssid
7912 * @bssid: Pointer to bssid
7913 * @operatingChannel: Operating channel
7914 *
7915 * This function is used to start the association process
7916 *
7917 * Return: 0 for success, non-zero for failure
7918 */
7919int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
7920 const u8 *ssid, size_t ssid_len,
7921 const u8 *bssid_hint, const u8 *bssid,
7922 u8 operatingChannel)
7923{
7924 int status = 0;
7925 hdd_wext_state_t *pWextState;
7926 hdd_context_t *pHddCtx;
7927 uint32_t roamId;
7928 tCsrRoamProfile *pRoamProfile;
7929 eCsrAuthType RSNAuthType;
7930 tSmeConfigParams *sme_config;
7931
7932 ENTER();
7933
7934 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7935 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7936
7937 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307938 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007939 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007940
7941 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
7942 hddLog(LOGE, FL("wrong SSID len"));
7943 return -EINVAL;
7944 }
7945
7946 pRoamProfile = &pWextState->roamProfile;
7947
7948 if (pRoamProfile) {
7949 hdd_station_ctx_t *pHddStaCtx;
7950 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7951
7952 if (HDD_WMM_USER_MODE_NO_QOS ==
7953 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
7954 /*QoS not enabled in cfg file */
7955 pRoamProfile->uapsd_mask = 0;
7956 } else {
7957 /*QoS enabled, update uapsd mask from cfg file */
7958 pRoamProfile->uapsd_mask =
7959 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
7960 }
7961
7962 pRoamProfile->SSIDs.numOfSSIDs = 1;
7963 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307964 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007965 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307966 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007967 ssid, ssid_len);
7968
7969 if (bssid) {
7970 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307971 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307972 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007973 /* Save BSSID in seperate variable as well, as RoamProfile
7974 BSSID is getting zeroed out in the association process. And in
7975 case of join failure we should send valid BSSID to supplicant
7976 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307977 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307978 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007979 } else if (bssid_hint) {
7980 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307981 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307982 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007983 /* Save BSSID in separate variable as well, as
7984 RoamProfile BSSID is getting zeroed out in the
7985 association process. And in case of join failure
7986 we should send valid BSSID to supplicant
7987 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307988 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307989 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007990 hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR),
7991 MAC_ADDR_ARRAY(bssid_hint));
7992 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307993 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05307994 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007995 }
7996
7997 hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"),
7998 pRoamProfile->SSIDs.SSIDList->SSID.length,
7999 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
8000 operatingChannel);
8001
8002 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
8003 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
8004 /*set gen ie */
8005 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
8006 /*set auth */
8007 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
8008 }
8009#ifdef FEATURE_WLAN_WAPI
8010 if (pAdapter->wapi_info.nWapiMode) {
8011 hddLog(LOG1,
8012 FL("Setting WAPI AUTH Type and Encryption Mode values"));
8013 switch (pAdapter->wapi_info.wapiAuthMode) {
8014 case WAPI_AUTH_MODE_PSK:
8015 {
8016 hddLog(LOG1,
8017 FL("WAPI AUTH TYPE: PSK: %d"),
8018 pAdapter->wapi_info.wapiAuthMode);
8019 pRoamProfile->AuthType.authType[0] =
8020 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
8021 break;
8022 }
8023 case WAPI_AUTH_MODE_CERT:
8024 {
8025 hddLog(LOG1,
8026 FL("WAPI AUTH TYPE: CERT: %d"),
8027 pAdapter->wapi_info.wapiAuthMode);
8028 pRoamProfile->AuthType.authType[0] =
8029 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
8030 break;
8031 }
8032 } /* End of switch */
8033 if (pAdapter->wapi_info.wapiAuthMode ==
8034 WAPI_AUTH_MODE_PSK
8035 || pAdapter->wapi_info.wapiAuthMode ==
8036 WAPI_AUTH_MODE_CERT) {
8037 hddLog(LOG1,
8038 FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI"));
8039 pRoamProfile->AuthType.numEntries = 1;
8040 pRoamProfile->EncryptionType.numEntries = 1;
8041 pRoamProfile->EncryptionType.encryptionType[0] =
8042 eCSR_ENCRYPT_TYPE_WPI;
8043 pRoamProfile->mcEncryptionType.numEntries = 1;
8044 pRoamProfile->mcEncryptionType.
8045 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
8046 }
8047 }
8048#endif /* FEATURE_WLAN_WAPI */
8049#ifdef WLAN_FEATURE_GTK_OFFLOAD
8050 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -08008051 if ((QDF_STA_MODE == pAdapter->device_mode) ||
8052 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008053 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
8054 sizeof(tSirGtkOffloadParams));
8055 pHddStaCtx->gtkOffloadReqParams.ulFlags =
8056 GTK_OFFLOAD_DISABLE;
8057 }
8058#endif
8059 pRoamProfile->csrPersona = pAdapter->device_mode;
8060
8061 if (operatingChannel) {
8062 pRoamProfile->ChannelInfo.ChannelList =
8063 &operatingChannel;
8064 pRoamProfile->ChannelInfo.numOfChannels = 1;
8065 } else {
8066 pRoamProfile->ChannelInfo.ChannelList = NULL;
8067 pRoamProfile->ChannelInfo.numOfChannels = 0;
8068 }
Krunal Sonib4326f22016-03-10 13:05:51 -08008069 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008070 && operatingChannel) {
8071 /*
8072 * Need to post the IBSS power save parameters
8073 * to WMA. WMA will configure this parameters
8074 * to firmware if power save is enabled by the
8075 * firmware.
8076 */
8077 status = hdd_set_ibss_power_save_params(pAdapter);
8078
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308079 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008080 hddLog(LOGE,
8081 FL("Set IBSS Power Save Params Failed"));
8082 return -EINVAL;
8083 }
8084 hdd_select_cbmode(pAdapter, operatingChannel);
8085 }
8086
8087 if (pHddCtx->config->policy_manager_enabled &&
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008088 (true == cds_is_connection_in_progress())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008089 hdd_err("Connection refused: conn in progress");
8090 return -EINVAL;
8091 }
8092
8093 /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect()
8094 * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state
8095 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
8096 * by either hdd_association_completion_handler() or hdd_dis_connect_handler() in sme_RoamCallback()
8097 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
8098 */
Krunal Sonib4326f22016-03-10 13:05:51 -08008099 if (QDF_STA_MODE == pAdapter->device_mode ||
8100 QDF_P2P_CLIENT_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008101 hddLog(LOG1,
8102 FL("Set HDD connState to eConnectionState_Connecting"));
8103 hdd_conn_set_connection_state(pAdapter,
8104 eConnectionState_Connecting);
8105 }
8106
8107 /* After 8-way handshake supplicant should give the scan command
8108 * in that it update the additional IEs, But because of scan
8109 * enhancements, the supplicant is not issuing the scan command now.
8110 * So the unicast frames which are sent from the host are not having
8111 * the additional IEs. If it is P2P CLIENT and there is no additional
8112 * IE present in roamProfile, then use the addtional IE form scan_info
8113 */
8114
Krunal Sonib4326f22016-03-10 13:05:51 -08008115 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008116 (!pRoamProfile->pAddIEScan)) {
8117 pRoamProfile->pAddIEScan =
8118 &pAdapter->scan_info.scanAddIE.addIEdata[0];
8119 pRoamProfile->nAddIEScanLength =
8120 pAdapter->scan_info.scanAddIE.length;
8121 }
8122 /*
8123 * When policy manager is enabled from ini file, we shouldn't
8124 * check for other concurrency rules.
8125 */
8126 if (!pHddCtx->config->policy_manager_enabled) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008127 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008128 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008129 pAdapter, pRoamProfile, &roamId))
8130 return 0;
8131 }
8132
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308133 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008134 if (!sme_config) {
8135 hdd_err("unable to allocate sme_config");
8136 return -ENOMEM;
8137 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308138 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008139 sme_get_config_param(pHddCtx->hHal, sme_config);
8140 /* These values are not sessionized. So, any change in these SME
8141 * configs on an older or parallel interface will affect the
8142 * cb mode. So, restoring the default INI params before starting
8143 * interfaces such as sta, cli etc.,
8144 */
8145 sme_config->csrConfig.channelBondingMode5GHz =
8146 pHddCtx->config->nChannelBondingMode5GHz;
8147 sme_config->csrConfig.channelBondingMode24GHz =
8148 pHddCtx->config->nChannelBondingMode24GHz;
8149 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308150 qdf_mem_free(sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008151
8152 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8153 pAdapter->sessionId, pRoamProfile,
8154 &roamId);
8155
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308156 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08008157 (QDF_STA_MODE == pAdapter->device_mode ||
8158 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008159 hddLog(LOGE,
8160 FL("sme_roam_connect (session %d) failed with "
8161 "status %d. -> NotConnected"),
8162 pAdapter->sessionId, status);
8163 /* change back to NotAssociated */
8164 hdd_conn_set_connection_state(pAdapter,
8165 eConnectionState_NotConnected);
8166 }
8167
8168 pRoamProfile->ChannelInfo.ChannelList = NULL;
8169 pRoamProfile->ChannelInfo.numOfChannels = 0;
8170
8171 } else {
8172 hddLog(LOGE, FL("No valid Roam profile"));
8173 return -EINVAL;
8174 }
8175 EXIT();
8176 return status;
8177}
8178
8179/**
8180 * wlan_hdd_cfg80211_set_auth_type() - set auth type
8181 * @pAdapter: Pointer to adapter
8182 * @auth_type: Auth type
8183 *
8184 * This function is used to set the authentication type (OPEN/SHARED).
8185 *
8186 * Return: 0 for success, non-zero for failure
8187 */
8188static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
8189 enum nl80211_auth_type auth_type)
8190{
8191 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8192 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8193
8194 ENTER();
8195
8196 /*set authentication type */
8197 switch (auth_type) {
8198 case NL80211_AUTHTYPE_AUTOMATIC:
8199 hddLog(LOG1,
8200 FL("set authentication type to AUTOSWITCH"));
8201 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
8202 break;
8203
8204 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008205 case NL80211_AUTHTYPE_FT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008206 hddLog(LOG1,
8207 FL("set authentication type to OPEN"));
8208 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8209 break;
8210
8211 case NL80211_AUTHTYPE_SHARED_KEY:
8212 hddLog(LOG1,
8213 FL("set authentication type to SHARED"));
8214 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
8215 break;
8216#ifdef FEATURE_WLAN_ESE
8217 case NL80211_AUTHTYPE_NETWORK_EAP:
8218 hddLog(LOG1,
8219 FL("set authentication type to CCKM WPA"));
8220 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
8221 break;
8222#endif
8223
8224 default:
8225 hddLog(LOGE,
8226 FL("Unsupported authentication type %d"), auth_type);
8227 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
8228 return -EINVAL;
8229 }
8230
8231 pWextState->roamProfile.AuthType.authType[0] =
8232 pHddStaCtx->conn_info.authType;
8233 return 0;
8234}
8235
8236/**
8237 * wlan_hdd_set_akm_suite() - set key management type
8238 * @pAdapter: Pointer to adapter
8239 * @key_mgmt: Key management type
8240 *
8241 * This function is used to set the key mgmt type(PSK/8021x).
8242 *
8243 * Return: 0 for success, non-zero for failure
8244 */
8245static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
8246{
8247 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8248
8249 ENTER();
8250
8251#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
8252#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
8253 /*set key mgmt type */
8254 switch (key_mgmt) {
8255 case WLAN_AKM_SUITE_PSK:
8256 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008257 case WLAN_AKM_SUITE_FT_PSK:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008258 hddLog(LOG1, FL("setting key mgmt type to PSK"));
8259 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
8260 break;
8261
8262 case WLAN_AKM_SUITE_8021X_SHA256:
8263 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008264 case WLAN_AKM_SUITE_FT_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008265 hddLog(LOG1,
8266 FL("setting key mgmt type to 8021x"));
8267 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8268 break;
8269#ifdef FEATURE_WLAN_ESE
8270#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
8271#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
8272 case WLAN_AKM_SUITE_CCKM:
8273 hddLog(LOG1,
8274 FL("setting key mgmt type to CCKM"));
8275 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
8276 break;
8277#endif
8278#ifndef WLAN_AKM_SUITE_OSEN
8279#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
8280#endif
8281 case WLAN_AKM_SUITE_OSEN:
8282 hddLog(LOG1,
8283 FL("setting key mgmt type to OSEN"));
8284 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
8285 break;
8286
8287 default:
8288 hddLog(LOGE,
8289 FL("Unsupported key mgmt type %d"), key_mgmt);
8290 return -EINVAL;
8291
8292 }
8293 return 0;
8294}
8295
8296/**
8297 * wlan_hdd_cfg80211_set_cipher() - set encryption type
8298 * @pAdapter: Pointer to adapter
8299 * @cipher: Cipher type
8300 * @ucast: Unicast flag
8301 *
8302 * This function is used to set the encryption type
8303 * (NONE/WEP40/WEP104/TKIP/CCMP).
8304 *
8305 * Return: 0 for success, non-zero for failure
8306 */
8307static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
8308 u32 cipher, bool ucast)
8309{
8310 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8311 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8312 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8313
8314 ENTER();
8315
8316 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008317 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008318 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8319 } else {
8320
8321 /*set encryption method */
8322 switch (cipher) {
8323 case IW_AUTH_CIPHER_NONE:
8324 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8325 break;
8326
8327 case WLAN_CIPHER_SUITE_WEP40:
8328 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
8329 break;
8330
8331 case WLAN_CIPHER_SUITE_WEP104:
8332 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
8333 break;
8334
8335 case WLAN_CIPHER_SUITE_TKIP:
8336 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
8337 break;
8338
8339 case WLAN_CIPHER_SUITE_CCMP:
8340 encryptionType = eCSR_ENCRYPT_TYPE_AES;
8341 break;
8342#ifdef FEATURE_WLAN_WAPI
8343 case WLAN_CIPHER_SUITE_SMS4:
8344 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
8345 break;
8346#endif
8347
8348#ifdef FEATURE_WLAN_ESE
8349 case WLAN_CIPHER_SUITE_KRK:
8350 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
8351 break;
8352#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8353 case WLAN_CIPHER_SUITE_BTK:
8354 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
8355 break;
8356#endif
8357#endif
8358 default:
8359 hddLog(LOGE,
8360 FL("Unsupported cipher type %d"), cipher);
8361 return -EOPNOTSUPP;
8362 }
8363 }
8364
8365 if (ucast) {
8366 hddLog(LOG1,
8367 FL("setting unicast cipher type to %d"), encryptionType);
8368 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
8369 pWextState->roamProfile.EncryptionType.numEntries = 1;
8370 pWextState->roamProfile.EncryptionType.encryptionType[0] =
8371 encryptionType;
8372 } else {
8373 hddLog(LOG1,
8374 FL("setting mcast cipher type to %d"), encryptionType);
8375 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
8376 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
8377 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
8378 encryptionType;
8379 }
8380
8381 return 0;
8382}
8383
8384/**
8385 * wlan_hdd_cfg80211_set_ie() - set IEs
8386 * @pAdapter: Pointer to adapter
8387 * @ie: Pointer ot ie
8388 * @ie: IE length
8389 *
8390 * Return: 0 for success, non-zero for failure
8391 */
8392int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
8393 size_t ie_len)
8394{
8395 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8396 const uint8_t *genie = ie;
8397 uint16_t remLen = ie_len;
8398#ifdef FEATURE_WLAN_WAPI
8399 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
8400 u16 *tmp;
8401 uint16_t akmsuiteCount;
8402 int *akmlist;
8403#endif
8404 ENTER();
8405
8406 /* clear previous assocAddIE */
8407 pWextState->assocAddIE.length = 0;
8408 pWextState->roamProfile.bWPSAssociation = false;
8409 pWextState->roamProfile.bOSENAssociation = false;
8410
8411 while (remLen >= 2) {
8412 uint16_t eLen = 0;
8413 uint8_t elementId;
8414 elementId = *genie++;
8415 eLen = *genie++;
8416 remLen -= 2;
8417
8418 hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), elementId, eLen);
8419
8420 switch (elementId) {
8421 case DOT11F_EID_WPA:
8422 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
8423 hddLog(LOGE, FL("Invalid WPA IE"));
8424 return -EINVAL;
8425 } else if (0 ==
8426 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
8427 uint16_t curAddIELen =
8428 pWextState->assocAddIE.length;
8429 hddLog(LOG1,
8430 FL("Set WPS IE(len %d)"), eLen + 2);
8431
8432 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8433 (pWextState->assocAddIE.length + eLen)) {
8434 hddLog(LOGE,
8435 FL("Cannot accommodate assocAddIE. Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308436 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008437 return -ENOMEM;
8438 }
8439 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8440 memcpy(pWextState->assocAddIE.addIEdata +
8441 curAddIELen, genie - 2, eLen + 2);
8442 pWextState->assocAddIE.length += eLen + 2;
8443
8444 pWextState->roamProfile.bWPSAssociation = true;
8445 pWextState->roamProfile.pAddIEAssoc =
8446 pWextState->assocAddIE.addIEdata;
8447 pWextState->roamProfile.nAddIEAssocLength =
8448 pWextState->assocAddIE.length;
8449 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
8450 hddLog(LOG1,
8451 FL("Set WPA IE (len %d)"), eLen + 2);
8452 memset(pWextState->WPARSNIE, 0,
8453 MAX_WPA_RSN_IE_LEN);
8454 memcpy(pWextState->WPARSNIE, genie - 2,
8455 (eLen + 2));
8456 pWextState->roamProfile.pWPAReqIE =
8457 pWextState->WPARSNIE;
8458 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
8459 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
8460 P2P_OUI_TYPE_SIZE))) {
8461 uint16_t curAddIELen =
8462 pWextState->assocAddIE.length;
8463 hddLog(LOG1,
8464 FL("Set P2P IE(len %d)"), eLen + 2);
8465
8466 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8467 (pWextState->assocAddIE.length + eLen)) {
8468 hddLog(LOGE,
8469 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308470 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008471 return -ENOMEM;
8472 }
8473 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
8474 memcpy(pWextState->assocAddIE.addIEdata +
8475 curAddIELen, genie - 2, eLen + 2);
8476 pWextState->assocAddIE.length += eLen + 2;
8477
8478 pWextState->roamProfile.pAddIEAssoc =
8479 pWextState->assocAddIE.addIEdata;
8480 pWextState->roamProfile.nAddIEAssocLength =
8481 pWextState->assocAddIE.length;
8482 }
8483#ifdef WLAN_FEATURE_WFD
8484 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
8485 WFD_OUI_TYPE_SIZE)) &&
8486 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -08008487 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008488 pAdapter->device_mode)) {
8489 uint16_t curAddIELen =
8490 pWextState->assocAddIE.length;
8491 hddLog(LOG1,
8492 FL("Set WFD IE(len %d)"), eLen + 2);
8493
8494 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8495 (pWextState->assocAddIE.length + eLen)) {
8496 hddLog(LOGE,
8497 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308498 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008499 return -ENOMEM;
8500 }
8501 /* WFD IE is saved to Additional IE ; it should
8502 * be accumulated to handle WPS IE + P2P IE +
8503 * WFD IE */
8504 memcpy(pWextState->assocAddIE.addIEdata +
8505 curAddIELen, genie - 2, eLen + 2);
8506 pWextState->assocAddIE.length += eLen + 2;
8507
8508 pWextState->roamProfile.pAddIEAssoc =
8509 pWextState->assocAddIE.addIEdata;
8510 pWextState->roamProfile.nAddIEAssocLength =
8511 pWextState->assocAddIE.length;
8512 }
8513#endif
8514 /* Appending HS 2.0 Indication Element in Assiciation Request */
8515 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
8516 HS20_OUI_TYPE_SIZE))) {
8517 uint16_t curAddIELen =
8518 pWextState->assocAddIE.length;
8519 hddLog(LOG1,
8520 FL("Set HS20 IE(len %d)"), eLen + 2);
8521
8522 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8523 (pWextState->assocAddIE.length + eLen)) {
8524 hddLog(LOGE,
8525 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308526 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008527 return -ENOMEM;
8528 }
8529 memcpy(pWextState->assocAddIE.addIEdata +
8530 curAddIELen, genie - 2, eLen + 2);
8531 pWextState->assocAddIE.length += eLen + 2;
8532
8533 pWextState->roamProfile.pAddIEAssoc =
8534 pWextState->assocAddIE.addIEdata;
8535 pWextState->roamProfile.nAddIEAssocLength =
8536 pWextState->assocAddIE.length;
8537 }
8538 /* Appending OSEN Information Element in Assiciation Request */
8539 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
8540 OSEN_OUI_TYPE_SIZE))) {
8541 uint16_t curAddIELen =
8542 pWextState->assocAddIE.length;
8543 hddLog(LOG1,
8544 FL("Set OSEN IE(len %d)"), eLen + 2);
8545
8546 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8547 (pWextState->assocAddIE.length + eLen)) {
8548 hddLog(LOGE,
8549 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308550 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008551 return -ENOMEM;
8552 }
8553 memcpy(pWextState->assocAddIE.addIEdata +
8554 curAddIELen, genie - 2, eLen + 2);
8555 pWextState->assocAddIE.length += eLen + 2;
8556
8557 pWextState->roamProfile.bOSENAssociation = true;
8558 pWextState->roamProfile.pAddIEAssoc =
8559 pWextState->assocAddIE.addIEdata;
8560 pWextState->roamProfile.nAddIEAssocLength =
8561 pWextState->assocAddIE.length;
8562 } else {
8563 uint16_t add_ie_len =
8564 pWextState->assocAddIE.length;
8565
8566 hdd_info("Set OSEN IE(len %d)", eLen + 2);
8567
8568 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8569 (pWextState->assocAddIE.length + eLen)) {
8570 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308571 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008572 return -ENOMEM;
8573 }
8574
8575 memcpy(pWextState->assocAddIE.addIEdata +
8576 add_ie_len, genie - 2, eLen + 2);
8577 pWextState->assocAddIE.length += eLen + 2;
8578
8579 pWextState->roamProfile.pAddIEAssoc =
8580 pWextState->assocAddIE.addIEdata;
8581 pWextState->roamProfile.nAddIEAssocLength =
8582 pWextState->assocAddIE.length;
8583 }
8584 break;
8585 case DOT11F_EID_RSN:
8586 hddLog(LOG1, FL("Set RSN IE(len %d)"), eLen + 2);
8587 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
8588 memcpy(pWextState->WPARSNIE, genie - 2,
8589 (eLen + 2));
8590 pWextState->roamProfile.pRSNReqIE =
8591 pWextState->WPARSNIE;
8592 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
8593 break;
8594 /*
8595 * Appending Extended Capabilities with Interworking bit set
8596 * in Assoc Req.
8597 *
8598 * In assoc req this EXT Cap will only be taken into account if
8599 * interworkingService bit is set to 1. Currently
8600 * driver is only interested in interworkingService capability
8601 * from supplicant. If in future any other EXT Cap info is
8602 * required from supplicat, it needs to be handled while
8603 * sending Assoc Req in LIM.
8604 */
8605 case DOT11F_EID_EXTCAP:
8606 {
8607 uint16_t curAddIELen =
8608 pWextState->assocAddIE.length;
8609 hddLog(LOG1,
8610 FL("Set Extended CAPS IE(len %d)"), eLen + 2);
8611
8612 if (SIR_MAC_MAX_ADD_IE_LENGTH <
8613 (pWextState->assocAddIE.length + eLen)) {
8614 hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308615 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008616 return -ENOMEM;
8617 }
8618 memcpy(pWextState->assocAddIE.addIEdata +
8619 curAddIELen, genie - 2, eLen + 2);
8620 pWextState->assocAddIE.length += eLen + 2;
8621
8622 pWextState->roamProfile.pAddIEAssoc =
8623 pWextState->assocAddIE.addIEdata;
8624 pWextState->roamProfile.nAddIEAssocLength =
8625 pWextState->assocAddIE.length;
8626 break;
8627 }
8628#ifdef FEATURE_WLAN_WAPI
8629 case WLAN_EID_WAPI:
8630 /* Setting WAPI Mode to ON=1 */
8631 pAdapter->wapi_info.nWapiMode = 1;
8632 hddLog(LOG1,
8633 FL("WAPI MODE IS %u"), pAdapter->wapi_info.nWapiMode);
8634 tmp = (u16 *) ie;
8635 tmp = tmp + 2; /* Skip element Id and Len, Version */
8636 akmsuiteCount = WPA_GET_LE16(tmp);
8637 tmp = tmp + 1;
8638 akmlist = (int *)(tmp);
8639 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
8640 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
8641 } else {
8642 hddLog(LOGE,
8643 FL("Invalid akmSuite count"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308644 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008645 return -EINVAL;
8646 }
8647
8648 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
8649 hddLog(LOG1,
8650 FL("WAPI AUTH MODE SET TO PSK"));
8651 pAdapter->wapi_info.wapiAuthMode =
8652 WAPI_AUTH_MODE_PSK;
8653 }
8654 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
8655 hddLog(LOG1,
8656 FL("WAPI AUTH MODE SET TO CERTIFICATE"));
8657 pAdapter->wapi_info.wapiAuthMode =
8658 WAPI_AUTH_MODE_CERT;
8659 }
8660 break;
8661#endif
8662 default:
8663 hddLog(LOGE,
8664 FL("Set UNKNOWN IE %X"), elementId);
8665 /* when Unknown IE is received we should break and continue
8666 * to the next IE in the buffer instead we were returning
8667 * so changing this to break */
8668 break;
8669 }
8670 genie += eLen;
8671 remLen -= eLen;
8672 }
8673 EXIT();
8674 return 0;
8675}
8676
8677/**
8678 * hdd_is_wpaie_present() - check for WPA ie
8679 * @ie: Pointer to ie
8680 * @ie_len: Ie length
8681 *
8682 * Parse the received IE to find the WPA IE
8683 *
8684 * Return: true if wpa ie is found else false
8685 */
8686static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
8687{
8688 uint8_t eLen = 0;
8689 uint16_t remLen = ie_len;
8690 uint8_t elementId = 0;
8691
8692 while (remLen >= 2) {
8693 elementId = *ie++;
8694 eLen = *ie++;
8695 remLen -= 2;
8696 if (eLen > remLen) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308697 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008698 "%s: IE length is wrong %d", __func__, eLen);
8699 return false;
8700 }
8701 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
8702 /* OUI - 0x00 0X50 0XF2
8703 * WPA Information Element - 0x01
8704 * WPA version - 0x01
8705 */
8706 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
8707 return true;
8708 }
8709 ie += eLen;
8710 remLen -= eLen;
8711 }
8712 return false;
8713}
8714
8715/**
8716 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
8717 * @pAdapter: Pointer to adapter
8718 * @req: Pointer to security parameters
8719 *
8720 * Return: 0 for success, non-zero for failure
8721 */
8722int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
8723 struct cfg80211_connect_params *req)
8724{
8725 int status = 0;
8726 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8727 ENTER();
8728
8729 /*set wpa version */
8730 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
8731
8732 if (req->crypto.wpa_versions) {
8733 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
8734 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
8735 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
8736 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
8737 }
8738 }
8739
8740 hddLog(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion);
8741
8742 /*set authentication type */
8743 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
8744
8745 if (0 > status) {
8746 hddLog(LOGE, FL("failed to set authentication type "));
8747 return status;
8748 }
8749
8750 /*set key mgmt type */
8751 if (req->crypto.n_akm_suites) {
8752 status =
8753 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
8754 if (0 > status) {
8755 hddLog(LOGE, FL("failed to set akm suite"));
8756 return status;
8757 }
8758 }
8759
8760 /*set pairwise cipher type */
8761 if (req->crypto.n_ciphers_pairwise) {
8762 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
8763 req->crypto.
8764 ciphers_pairwise[0],
8765 true);
8766 if (0 > status) {
8767 hddLog(LOGE, FL("failed to set unicast cipher type"));
8768 return status;
8769 }
8770 } else {
8771 /*Reset previous cipher suite to none */
8772 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
8773 if (0 > status) {
8774 hddLog(LOGE, FL("failed to set unicast cipher type"));
8775 return status;
8776 }
8777 }
8778
8779 /*set group cipher type */
8780 status =
8781 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
8782 false);
8783
8784 if (0 > status) {
8785 hddLog(LOGE, FL("failed to set mcast cipher type"));
8786 return status;
8787 }
8788#ifdef WLAN_FEATURE_11W
8789 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
8790#endif
8791
8792 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
8793 if (req->ie_len) {
8794 status =
8795 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
8796 if (0 > status) {
8797 hddLog(LOGE, FL("failed to parse the WPA/RSN IE"));
8798 return status;
8799 }
8800 }
8801
8802 /*incase of WEP set default key information */
8803 if (req->key && req->key_len) {
8804 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
8805 || (WLAN_CIPHER_SUITE_WEP104 ==
8806 req->crypto.ciphers_pairwise[0])
8807 ) {
8808 if (IW_AUTH_KEY_MGMT_802_1X
8809 ==
8810 (pWextState->
8811 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
8812 hddLog(LOGE,
8813 FL("Dynamic WEP not supported"));
8814 return -EOPNOTSUPP;
8815 } else {
8816 u8 key_len = req->key_len;
8817 u8 key_idx = req->key_idx;
8818
8819 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
8820 key_len)
8821 && (CSR_MAX_NUM_KEY > key_idx)
8822 ) {
8823 hddLog(LOG1,
8824 FL("setting default wep key, key_idx = %hu key_len %hu"),
8825 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308826 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008827 Keys.
8828 KeyMaterial[key_idx][0],
8829 req->key, key_len);
8830 pWextState->roamProfile.Keys.
8831 KeyLength[key_idx] = (u8) key_len;
8832 pWextState->roamProfile.Keys.
8833 defaultIndex = (u8) key_idx;
8834 }
8835 }
8836 }
8837 }
8838
8839 return status;
8840}
8841
8842/**
8843 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
8844 * @pAdapter: Pointer to adapter
8845 *
8846 * This function is used to disconnect from previous connection
8847 *
8848 * Return: 0 for success, non-zero for failure
8849 */
8850static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
8851{
8852 unsigned long rc;
8853 hdd_station_ctx_t *pHddStaCtx;
8854 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308855 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008856
8857 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8858
8859 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
8860
8861 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +05308862 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
8863 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
8864 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008865 hdd_conn_set_connection_state(pAdapter,
8866 eConnectionState_Disconnecting);
8867 /* Issue disconnect to CSR */
8868 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308869
8870 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8871 pAdapter->sessionId,
8872 eCSR_DISCONNECT_REASON_UNSPECIFIED);
8873 /*
8874 * Wait here instead of returning directly, this will block the
8875 * next connect command and allow processing of the scan for
8876 * ssid and the previous connect command in CSR. Else we might
8877 * hit some race conditions leading to SME and HDD out of sync.
8878 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308879 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308880 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
8881 } else if (0 != status) {
8882 hdd_err("csrRoamDisconnect failure, returned %d",
8883 (int)status);
8884 pHddStaCtx->staDebugState = status;
8885 result = -EINVAL;
8886 goto disconnected;
8887 }
8888
8889 rc = wait_for_completion_timeout(
8890 &pAdapter->disconnect_comp_var,
8891 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308892 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308893 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
8894 pAdapter->sessionId, pHddStaCtx->staDebugState);
8895 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008896 }
8897 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308898 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008899 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308900 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008901 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308902 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008903 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308904 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008905 }
8906 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +05308907disconnected:
8908 hdd_info("Set HDD connState to eConnectionState_NotConnected");
8909 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
8910 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008911}
8912
8913/**
8914 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
8915 * @wiphy: Pointer to wiphy
8916 * @dev: Pointer to network device
8917 * @req: Pointer to cfg80211 connect request
8918 *
8919 * This function is used to start the association process
8920 *
8921 * Return: 0 for success, non-zero for failure
8922 */
8923static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8924 struct net_device *ndev,
8925 struct cfg80211_connect_params *req)
8926{
8927 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05308928 u16 channel;
8929#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
8930 const u8 *bssid_hint = req->bssid_hint;
8931#else
8932 const u8 *bssid_hint = NULL;
8933#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008934 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8935 hdd_context_t *pHddCtx;
8936
8937 ENTER();
8938
Anurag Chouhan6d760662016-02-20 16:05:43 +05308939 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008940 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8941 return -EINVAL;
8942 }
8943
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308944 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008945 TRACE_CODE_HDD_CFG80211_CONNECT,
8946 pAdapter->sessionId, pAdapter->device_mode));
8947 hddLog(LOG1, FL("Device_mode %s(%d)"),
8948 hdd_device_mode_to_string(pAdapter->device_mode),
8949 pAdapter->device_mode);
8950
Krunal Sonib4326f22016-03-10 13:05:51 -08008951 if (pAdapter->device_mode != QDF_STA_MODE &&
8952 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008953 hddLog(LOGE, FL("Device_mode %s(%d) is not supported"),
8954 hdd_device_mode_to_string(pAdapter->device_mode),
8955 pAdapter->device_mode);
8956 return -EINVAL;
8957 }
8958
8959 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8960 if (!pHddCtx) {
8961 hddLog(LOGE, FL("HDD context is null"));
8962 return -EINVAL;
8963 }
8964
8965 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308966 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008967 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008968 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008969 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -08008970 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008971 pAdapter->device_mode),
8972 req->channel->hw_value, HW_MODE_20_MHZ)) {
8973 hdd_err("This concurrency combination is not allowed");
8974 return -ECONNREFUSED;
8975 }
8976 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008977 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -08008978 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008979 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
8980 hdd_err("This concurrency combination is not allowed");
8981 return -ECONNREFUSED;
8982 }
8983 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008984 wlan_hdd_disable_roaming(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008985
8986 /*Try disconnecting if already in connected state */
8987 status = wlan_hdd_try_disconnect(pAdapter);
8988 if (0 > status) {
8989 hddLog(LOGE,
8990 FL("Failed to disconnect the existing connection"));
8991 return -EALREADY;
8992 }
8993
8994 /*initialise security parameters */
8995 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
8996
8997 if (0 > status) {
8998 hddLog(LOGE,
8999 FL("failed to set security params"));
9000 return status;
9001 }
9002
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05309003 if (req->channel)
9004 channel = req->channel->hw_value;
9005 else
9006 channel = 0;
9007 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
9008 req->ssid_len, req->bssid,
9009 bssid_hint, channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009010 if (0 > status) {
9011 hddLog(LOGE, FL("connect failed"));
9012 return status;
9013 }
9014 EXIT();
9015 return status;
9016}
9017
9018/**
9019 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
9020 * @wiphy: Pointer to wiphy
9021 * @dev: Pointer to network device
9022 * @req: Pointer to cfg80211 connect request
9023 *
9024 * Return: 0 for success, non-zero for failure
9025 */
9026static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
9027 struct net_device *ndev,
9028 struct cfg80211_connect_params *req)
9029{
9030 int ret;
9031 cds_ssr_protect(__func__);
9032 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
9033 cds_ssr_unprotect(__func__);
9034
9035 return ret;
9036}
9037
9038/**
9039 * wlan_hdd_disconnect() - hdd disconnect api
9040 * @pAdapter: Pointer to adapter
9041 * @reason: Disconnect reason code
9042 *
9043 * This function is used to issue a disconnect request to SME
9044 *
9045 * Return: 0 for success, non-zero for failure
9046 */
9047int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
9048{
9049 int status, result = 0;
9050 unsigned long rc;
9051 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9052 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9053
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309054 ENTER();
9055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009056 status = wlan_hdd_validate_context(pHddCtx);
9057
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309058 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009059 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009060
9061 /*stop tx queues */
9062 hddLog(LOG1, FL("Disabling queues"));
9063 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
9064 WLAN_CONTROL_PATH);
9065 hddLog(LOG1,
9066 FL("Set HDD connState to eConnectionState_Disconnecting"));
9067 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
9068 INIT_COMPLETION(pAdapter->disconnect_comp_var);
9069
9070 /*issue disconnect */
9071
9072 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9073 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +05309074 /*
9075 * Wait here instead of returning directly, this will block the next
9076 * connect command and allow processing of the scan for ssid and
9077 * the previous connect command in CSR. Else we might hit some
9078 * race conditions leading to SME and HDD out of sync.
9079 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309080 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309081 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009082 } else if (0 != status) {
9083 hddLog(LOGE,
9084 FL("csr_roam_disconnect failure, returned %d"),
9085 (int)status);
9086 pHddStaCtx->staDebugState = status;
9087 result = -EINVAL;
9088 goto disconnected;
9089 }
9090 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
9091 msecs_to_jiffies
9092 (WLAN_WAIT_TIME_DISCONNECT));
9093
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309094 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009095 hddLog(LOGE,
9096 FL("Failed to disconnect, timed out"));
9097 result = -ETIMEDOUT;
9098 }
9099disconnected:
9100 hddLog(LOG1,
9101 FL("Set HDD connState to eConnectionState_NotConnected"));
9102 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
9103#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
9104 /* Sending disconnect event to userspace for kernel version < 3.11
9105 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
9106 */
9107 hddLog(LOG1, FL("Send disconnected event to userspace"));
Ryan Hsua335c162016-01-21 12:12:20 -08009108 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, NULL, 0,
9109#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
9110 false,
9111#endif
9112 GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113#endif
9114
9115 return result;
9116}
9117
9118/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009119 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
9120 * @reason: ieee80211 reason code.
9121 *
9122 * This utility function helps log string conversion of reason code.
9123 *
9124 * Return: string conversion of reason code, if match found;
9125 * "Unknown" otherwise.
9126 */
9127static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
9128{
9129 switch (reason) {
9130 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
9131 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
9132 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
9133 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
9134 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
9135 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
9136 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
9137 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
9138 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
9139 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
9140 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
9141 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
9142 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
9143 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
9144 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
9145 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
9146 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
9147 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
9148 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
9149 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
9150 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
9151 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
9152 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
9153 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
9154 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
9155 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
9156 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
9157 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
9158 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
9159 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
9160 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
9161 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
9162 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
9163 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
9164 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
9165 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
9166 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
9167 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
9168 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
9169 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
9170 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
9171 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
9172 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
9173 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
9174 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
9175 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
9176 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
9177 default:
9178 return "Unknown";
9179 }
9180}
9181
9182/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9184 * @wiphy: Pointer to wiphy
9185 * @dev: Pointer to network device
9186 * @reason: Disconnect reason code
9187 *
9188 * This function is used to issue a disconnect request to SME
9189 *
9190 * Return: 0 for success, non-zero for failure
9191 */
9192static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9193 struct net_device *dev, u16 reason)
9194{
9195 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9196 int status;
9197 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9198 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9199#ifdef FEATURE_WLAN_TDLS
9200 uint8_t staIdx;
9201#endif
9202
9203 ENTER();
9204
Anurag Chouhan6d760662016-02-20 16:05:43 +05309205 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009206 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9207 return -EINVAL;
9208 }
9209
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309210 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009211 TRACE_CODE_HDD_CFG80211_DISCONNECT,
9212 pAdapter->sessionId, reason));
9213 hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"),
9214 hdd_device_mode_to_string(pAdapter->device_mode),
9215 pAdapter->device_mode, reason);
9216
9217 status = wlan_hdd_validate_context(pHddCtx);
9218
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309219 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009220 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009221
9222 /* Issue disconnect request to SME, if station is in connected state */
9223 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
9224 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
9225 eCsrRoamDisconnectReason reasonCode =
9226 eCSR_DISCONNECT_REASON_UNSPECIFIED;
9227 hdd_scaninfo_t *pScanInfo;
9228
9229 switch (reason) {
9230 case WLAN_REASON_MIC_FAILURE:
9231 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
9232 break;
9233
9234 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
9235 case WLAN_REASON_DISASSOC_AP_BUSY:
9236 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
9237 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
9238 break;
9239
9240 case WLAN_REASON_PREV_AUTH_NOT_VALID:
9241 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
9242 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
9243 break;
9244
9245 case WLAN_REASON_DEAUTH_LEAVING:
9246 reasonCode =
9247 pHddCtx->config->
9248 gEnableDeauthToDisassocMap ?
9249 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
9250 eCSR_DISCONNECT_REASON_DEAUTH;
9251 break;
9252 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
9253 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
9254 break;
9255 default:
9256 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
9257 break;
9258 }
9259 hddLog(LOG1,
9260 FL("convert to internal reason %d to reasonCode %d"),
9261 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262 pScanInfo = &pAdapter->scan_info;
9263 if (pScanInfo->mScanPending) {
9264 hddLog(LOG1,
9265 FL("Disconnect is in progress, Aborting Scan"));
9266 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
9267 eCSR_SCAN_ABORT_DEFAULT);
9268 }
9269#ifdef FEATURE_WLAN_TDLS
9270 /* First clean up the tdls peers if any */
9271 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
9272 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
9273 pAdapter->sessionId)
9274 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
9275 uint8_t *mac;
9276 mac =
9277 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
9278 hddLog(LOG1,
9279 "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d "
9280 MAC_ADDRESS_STR, __func__,
9281 pHddCtx->tdlsConnInfo[staIdx].staId,
9282 pAdapter->sessionId,
9283 MAC_ADDR_ARRAY(mac));
9284 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
9285 (pAdapter),
9286 pAdapter->sessionId, mac);
9287 }
9288 }
9289#endif
9290 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"),
9291 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009292 hdd_info("Disconnect request from user space with reason: %s",
9293 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009294 status = wlan_hdd_disconnect(pAdapter, reasonCode);
9295 if (0 != status) {
9296 hddLog(LOGE,
9297 FL("failure, returned %d"), status);
9298 return -EINVAL;
9299 }
9300 } else {
9301 hddLog(LOGE,
9302 FL("unexpected cfg disconnect called while in state (%d)"),
9303 pHddStaCtx->conn_info.connState);
9304 }
9305
9306 return status;
9307}
9308
9309/**
9310 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
9311 * @wiphy: Pointer to wiphy
9312 * @dev: Pointer to network device
9313 * @reason: Disconnect reason code
9314 *
9315 * Return: 0 for success, non-zero for failure
9316 */
9317static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
9318 struct net_device *dev, u16 reason)
9319{
9320 int ret;
9321 cds_ssr_protect(__func__);
9322 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
9323 cds_ssr_unprotect(__func__);
9324
9325 return ret;
9326}
9327
9328/**
9329 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
9330 * @pAdapter: Pointer to adapter
9331 * @param: Pointer to IBSS parameters
9332 *
9333 * This function is used to initialize the security settings in IBSS mode
9334 *
9335 * Return: 0 for success, non-zero for failure
9336 */
9337static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
9338 struct cfg80211_ibss_params
9339 *params)
9340{
9341 int status = 0;
9342 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9343 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9344 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9345
9346 ENTER();
9347
9348 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309349 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009350 pHddStaCtx->ibss_enc_key_installed = 0;
9351
9352 if (params->ie_len && (NULL != params->ie)) {
9353 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9354 params->ie_len, WLAN_EID_RSN)) {
9355 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9356 encryptionType = eCSR_ENCRYPT_TYPE_AES;
9357 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
9358 tDot11fIEWPA dot11WPAIE;
9359 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9360 u8 *ie;
9361
9362 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
9363 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
9364 params->ie_len,
9365 DOT11F_EID_WPA);
9366 if (NULL != ie) {
9367 pWextState->wpaVersion =
9368 IW_AUTH_WPA_VERSION_WPA;
9369 /* Unpack the WPA IE */
9370 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
9371 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
9372 &ie[2 + 4],
9373 ie[1] - 4, &dot11WPAIE);
9374 /*Extract the multicast cipher, the encType for unicast
9375 cipher for wpa-none is none */
9376 encryptionType =
9377 hdd_translate_wpa_to_csr_encryption_type
9378 (dot11WPAIE.multicast_cipher);
9379 }
9380 }
9381
9382 status =
9383 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
9384 params->ie_len);
9385
9386 if (0 > status) {
9387 hddLog(LOGE, FL("failed to parse WPA/RSN IE"));
9388 return status;
9389 }
9390 }
9391
9392 pWextState->roamProfile.AuthType.authType[0] =
9393 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
9394
9395 if (params->privacy) {
9396 /* Security enabled IBSS, At this time there is no information
9397 * available about the security paramters, so initialise the
9398 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
9399 * The correct security parameters will be updated later in
9400 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
9401 * set inorder enable privacy bit in beacons
9402 */
9403
9404 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9405 }
9406 hddLog(LOG2, FL("encryptionType=%d"), encryptionType);
9407 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
9408 pWextState->roamProfile.EncryptionType.numEntries = 1;
9409 pWextState->roamProfile.EncryptionType.encryptionType[0] =
9410 encryptionType;
9411 return status;
9412}
9413
9414/**
9415 * __wlan_hdd_cfg80211_join_ibss() - join ibss
9416 * @wiphy: Pointer to wiphy
9417 * @dev: Pointer to network device
9418 * @param: Pointer to IBSS join parameters
9419 *
9420 * This function is used to create/join an IBSS network
9421 *
9422 * Return: 0 for success, non-zero for failure
9423 */
9424static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9425 struct net_device *dev,
9426 struct cfg80211_ibss_params *params)
9427{
9428 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9429 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9430 tCsrRoamProfile *pRoamProfile;
9431 int status;
9432 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9433 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +05309434 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436
9437 ENTER();
9438
Anurag Chouhan6d760662016-02-20 16:05:43 +05309439 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9441 return -EINVAL;
9442 }
9443
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309444 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009445 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
9446 pAdapter->sessionId, pAdapter->device_mode));
9447 hddLog(LOG1, FL("Device_mode %s(%d)"),
9448 hdd_device_mode_to_string(pAdapter->device_mode),
9449 pAdapter->device_mode);
9450
9451 status = wlan_hdd_validate_context(pHddCtx);
9452
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309453 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009455
9456 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +05309457 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009458 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9459 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9460 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9461 int indx;
9462
9463 /* Get channel number */
9464 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009465 params->
9466 chandef.
9467 chan->
9468 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009469
9470 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9471 validChan, &numChans)) {
9472 hddLog(LOGE, FL("No valid channel list"));
9473 return -EOPNOTSUPP;
9474 }
9475
9476 for (indx = 0; indx < numChans; indx++) {
9477 if (channelNum == validChan[indx]) {
9478 break;
9479 }
9480 }
9481 if (indx >= numChans) {
9482 hddLog(LOGE,
9483 FL("Not valid Channel %d"), channelNum);
9484 return -EINVAL;
9485 }
9486 }
9487
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009488 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489 HW_MODE_20_MHZ)) {
9490 hdd_err("This concurrency combination is not allowed");
9491 return -ECONNREFUSED;
9492 }
9493 if (pHddCtx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309494 status = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309495 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496 hdd_err("ERR: clear event failed");
9497
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05309498 status = cds_current_connections_update(pAdapter->sessionId,
9499 channelNum,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05309500 SIR_UPDATE_REASON_JOIN_IBSS);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309501 if (QDF_STATUS_E_FAILURE == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009502 hdd_err("ERROR: connections update failed!!");
9503 return -EINVAL;
9504 }
9505
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309506 if (QDF_STATUS_SUCCESS == status) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309507 status = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309508 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309509 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 return -EINVAL;
9511 }
9512 }
9513 }
9514
9515 /*Try disconnecting if already in connected state */
9516 status = wlan_hdd_try_disconnect(pAdapter);
9517 if (0 > status) {
9518 hddLog(LOGE,
9519 FL("Failed to disconnect the existing IBSS connection"));
9520 return -EALREADY;
9521 }
9522
9523 pRoamProfile = &pWextState->roamProfile;
9524
9525 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
9526 hddLog(LOGE,
9527 FL("Interface type is not set to IBSS"));
9528 return -EINVAL;
9529 }
9530
9531 /* enable selected protection checks in IBSS mode */
9532 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
9533
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309534 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009535 WNI_CFG_IBSS_ATIM_WIN_SIZE,
9536 pHddCtx->config->
9537 ibssATIMWinSize)) {
9538 hddLog(LOGE,
9539 FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"));
9540 }
9541
9542 /* BSSID is provided by upper layers hence no need to AUTO generate */
9543 if (NULL != params->bssid) {
9544 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309545 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009546 hddLog(LOGE,
9547 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
9548 return -EIO;
9549 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309550 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009551 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
9552 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309553 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009554 hddLog(LOGE,
9555 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
9556 return -EIO;
9557 }
Anurag Chouhanc5548422016-02-24 18:33:27 +05309558 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009559 }
9560 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
9561 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
9562 pRoamProfile->beaconInterval = params->beacon_interval;
9563 else {
9564 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
9565 hddLog(LOG2,
9566 FL("input beacon interval %d TU is invalid, use default %d TU"),
9567 params->beacon_interval, pRoamProfile->beaconInterval);
9568 }
9569
9570 /* Set Channel */
9571 if (channelNum) {
9572 /* Set the Operational Channel */
9573 hddLog(LOG2, FL("set channel %d"), channelNum);
9574 pRoamProfile->ChannelInfo.numOfChannels = 1;
9575 pHddStaCtx->conn_info.operationChannel = channelNum;
9576 pRoamProfile->ChannelInfo.ChannelList =
9577 &pHddStaCtx->conn_info.operationChannel;
9578 }
9579
9580 /* Initialize security parameters */
9581 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
9582 if (status < 0) {
9583 hddLog(LOGE,
9584 FL("failed to set security parameters"));
9585 return status;
9586 }
9587
9588 /* Issue connect start */
9589 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
9590 params->ssid_len,
9591 bssid.bytes,
9592 NULL,
9593 pHddStaCtx->conn_info.
9594 operationChannel);
9595
9596 if (0 > status) {
9597 hddLog(LOGE, FL("connect failed"));
9598 return status;
9599 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309600 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009601 return 0;
9602}
9603
9604/**
9605 * wlan_hdd_cfg80211_join_ibss() - join ibss
9606 * @wiphy: Pointer to wiphy
9607 * @dev: Pointer to network device
9608 * @param: Pointer to IBSS join parameters
9609 *
9610 * This function is used to create/join an IBSS network
9611 *
9612 * Return: 0 for success, non-zero for failure
9613 */
9614static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
9615 struct net_device *dev,
9616 struct cfg80211_ibss_params *params)
9617{
9618 int ret = 0;
9619
9620 cds_ssr_protect(__func__);
9621 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
9622 cds_ssr_unprotect(__func__);
9623
9624 return ret;
9625}
9626
9627/**
9628 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
9629 * @wiphy: Pointer to wiphy
9630 * @dev: Pointer to network device
9631 *
9632 * This function is used to leave an IBSS network
9633 *
9634 * Return: 0 for success, non-zero for failure
9635 */
9636static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9637 struct net_device *dev)
9638{
9639 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9640 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9641 tCsrRoamProfile *pRoamProfile;
9642 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9643 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309644 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +05309645 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08009646 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009647
9648 ENTER();
9649
Anurag Chouhan6d760662016-02-20 16:05:43 +05309650 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009651 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9652 return -EINVAL;
9653 }
9654
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309655 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009656 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
9657 pAdapter->sessionId,
9658 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
9659 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309660 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009661 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009662
9663 hddLog(LOG1, FL("Device_mode %s(%d)"),
9664 hdd_device_mode_to_string(pAdapter->device_mode),
9665 pAdapter->device_mode);
9666 if (NULL == pWextState) {
9667 hddLog(LOGE, FL("Data Storage Corruption"));
9668 return -EIO;
9669 }
9670
9671 pRoamProfile = &pWextState->roamProfile;
9672
9673 /* Issue disconnect only if interface type is set to IBSS */
9674 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
9675 hddLog(LOGE,
9676 FL("BSS Type is not set to IBSS"));
9677 return -EINVAL;
9678 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -08009679 /* Clearing add IE of beacon */
9680 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
9681 sizeof(tSirMacAddr));
9682 updateIE.smeSessionId = pAdapter->sessionId;
9683 updateIE.ieBufferlength = 0;
9684 updateIE.pAdditionIEBuffer = NULL;
9685 updateIE.append = true;
9686 updateIE.notify = true;
9687 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
9688 &updateIE,
9689 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
9690 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
9691 }
9692
9693 /* Reset WNI_CFG_PROBE_RSP Flags */
9694 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695
9696 /* Issue Disconnect request */
9697 INIT_COMPLETION(pAdapter->disconnect_comp_var);
9698 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9699 pAdapter->sessionId,
9700 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309701 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 hddLog(LOGE,
9703 FL("sme_roam_disconnect failed hal_status(%d)"),
9704 hal_status);
9705 return -EAGAIN;
9706 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +05309707
9708 /* wait for mc thread to cleanup and then return to upper stack
9709 * so by the time upper layer calls the change interface, we are
9710 * all set to proceed further
9711 */
9712 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
9713 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9714 if (!rc) {
9715 hdd_err("Failed to disconnect, timed out");
9716 return -ETIMEDOUT;
9717 }
9718
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309719 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009720 return 0;
9721}
9722
9723/**
9724 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
9725 * @wiphy: Pointer to wiphy
9726 * @dev: Pointer to network device
9727 *
9728 * This function is used to leave an IBSS network
9729 *
9730 * Return: 0 for success, non-zero for failure
9731 */
9732static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9733 struct net_device *dev)
9734{
9735 int ret = 0;
9736
9737 cds_ssr_protect(__func__);
9738 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
9739 cds_ssr_unprotect(__func__);
9740
9741 return ret;
9742}
9743
9744/**
9745 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9746 * @wiphy: Pointer to wiphy
9747 * @changed: Parameters changed
9748 *
9749 * This function is used to set the phy parameters. RTS Threshold/FRAG
9750 * Threshold/Retry Count etc.
9751 *
9752 * Return: 0 for success, non-zero for failure
9753 */
9754static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
9755 u32 changed)
9756{
9757 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9758 tHalHandle hHal = pHddCtx->hHal;
9759 int status;
9760
9761 ENTER();
9762
Anurag Chouhan6d760662016-02-20 16:05:43 +05309763 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009764 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9765 return -EINVAL;
9766 }
9767
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309768 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
9770 NO_SESSION, wiphy->rts_threshold));
9771 status = wlan_hdd_validate_context(pHddCtx);
9772
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309773 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009774 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775
9776 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
9777 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
9778 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
9779
9780 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
9781 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
9782 hddLog(LOGE,
9783 FL("Invalid RTS Threshold value %u"),
9784 rts_threshold);
9785 return -EINVAL;
9786 }
9787
9788 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
9789 rts_threshold)) {
9790 hddLog(LOGE,
9791 FL("sme_cfg_set_int failed for rts_threshold value %u"),
9792 rts_threshold);
9793 return -EIO;
9794 }
9795
9796 hddLog(LOG2, FL("set rts threshold %u"), rts_threshold);
9797 }
9798
9799 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
9800 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
9801 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
9802 wiphy->frag_threshold;
9803
9804 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
9805 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
9806 hddLog(LOGE,
9807 FL("Invalid frag_threshold value %hu"),
9808 frag_threshold);
9809 return -EINVAL;
9810 }
9811
9812 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
9813 frag_threshold)) {
9814 hddLog(LOGE,
9815 FL("sme_cfg_set_int failed for frag_threshold value %hu"),
9816 frag_threshold);
9817 return -EIO;
9818 }
9819
9820 hddLog(LOG2, FL("set frag threshold %hu"), frag_threshold);
9821 }
9822
9823 if ((changed & WIPHY_PARAM_RETRY_SHORT)
9824 || (changed & WIPHY_PARAM_RETRY_LONG)) {
9825 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
9826 wiphy->retry_short : wiphy->retry_long;
9827
9828 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
9829 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
9830 hddLog(LOGE,
9831 FL("Invalid Retry count %hu"), retry_value);
9832 return -EINVAL;
9833 }
9834
9835 if (changed & WIPHY_PARAM_RETRY_SHORT) {
9836 if (0 != sme_cfg_set_int(hHal,
9837 WNI_CFG_LONG_RETRY_LIMIT,
9838 retry_value)) {
9839 hddLog(LOGE,
9840 FL("sme_cfg_set_int failed for long retry count %hu"),
9841 retry_value);
9842 return -EIO;
9843 }
9844 hddLog(LOG2,
9845 FL("set long retry count %hu"), retry_value);
9846 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
9847 if (0 != sme_cfg_set_int(hHal,
9848 WNI_CFG_SHORT_RETRY_LIMIT,
9849 retry_value)) {
9850 hddLog(LOGE,
9851 FL("sme_cfg_set_int failed for short retry count %hu"),
9852 retry_value);
9853 return -EIO;
9854 }
9855 hddLog(LOG2,
9856 FL("set short retry count %hu"), retry_value);
9857 }
9858 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309859 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009860 return 0;
9861}
9862
9863/**
9864 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9865 * @wiphy: Pointer to wiphy
9866 * @changed: Parameters changed
9867 *
9868 * Return: 0 for success, non-zero for failure
9869 */
9870static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
9871{
9872 int ret;
9873
9874 cds_ssr_protect(__func__);
9875 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
9876 cds_ssr_unprotect(__func__);
9877
9878 return ret;
9879}
9880
9881/**
9882 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
9883 * key
9884 * @wiphy: Pointer to wiphy
9885 * @dev: Pointer to network device
9886 * @key_index: Key index
9887 *
9888 * Return: 0
9889 */
9890static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9891 struct net_device *netdev,
9892 u8 key_index)
9893{
9894 ENTER();
9895 return 0;
9896}
9897
9898/**
9899 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
9900 * wlan_hdd_set_default_mgmt_key
9901 * @wiphy: pointer to wiphy
9902 * @netdev: pointer to net_device structure
9903 * @key_index: key index
9904 *
9905 * Return: 0 on success, error number on failure
9906 */
9907static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9908 struct net_device *netdev,
9909 u8 key_index)
9910{
9911 int ret;
9912
9913 cds_ssr_protect(__func__);
9914 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
9915 cds_ssr_unprotect(__func__);
9916
9917 return ret;
9918}
9919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009920/**
9921 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
9922 * @wiphy: Pointer to wiphy
9923 * @dev: Pointer to network device
9924 * @params: Pointer to tx queue parameters
9925 *
9926 * Return: 0
9927 */
9928static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
9929 struct net_device *dev,
9930 struct ieee80211_txq_params *params)
9931{
9932 ENTER();
9933 return 0;
9934}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009935
9936/**
9937 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
9938 * @wiphy: pointer to wiphy
9939 * @netdev: pointer to net_device structure
9940 * @params: pointer to ieee80211_txq_params
9941 *
9942 * Return: 0 on success, error number on failure
9943 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009944static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
9945 struct net_device *dev,
9946 struct ieee80211_txq_params *params)
9947{
9948 int ret;
9949
9950 cds_ssr_protect(__func__);
9951 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
9952 cds_ssr_unprotect(__func__);
9953
9954 return ret;
9955}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009956
9957/**
9958 * __wlan_hdd_cfg80211_del_station() - delete station v2
9959 * @wiphy: Pointer to wiphy
9960 * @param: Pointer to delete station parameter
9961 *
9962 * Return: 0 for success, non-zero for failure
9963 */
9964static
9965int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9966 struct net_device *dev,
9967 struct tagCsrDelStaParams *pDelStaParams)
9968{
9969 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9970 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +05309971 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 hdd_hostapd_state_t *hapd_state;
9973 int status;
9974 uint8_t staId;
9975 uint8_t *mac;
9976
9977 ENTER();
9978
Anurag Chouhan6d760662016-02-20 16:05:43 +05309979 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009980 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9981 return -EINVAL;
9982 }
9983
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309984 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009985 TRACE_CODE_HDD_CFG80211_DEL_STA,
9986 pAdapter->sessionId, pAdapter->device_mode));
9987
9988 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9989 status = wlan_hdd_validate_context(pHddCtx);
9990
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309991 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009993
9994 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
9995
Krunal Sonib4326f22016-03-10 13:05:51 -08009996 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
9997 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998
9999 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10000 if (!hapd_state) {
10001 hddLog(LOGE, "%s: Hostapd State is Null", __func__);
10002 return 0;
10003 }
10004
Anurag Chouhanc5548422016-02-24 18:33:27 +053010005 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010006 uint16_t i;
10007 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
10008 if ((pAdapter->aStaInfo[i].isUsed) &&
10009 (!pAdapter->aStaInfo[i].
10010 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010011 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012 mac,
10013 pAdapter->aStaInfo[i].
10014 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010015 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010016 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
10017 hdd_ipa_wlan_evt(pAdapter,
10018 pAdapter->
10019 aStaInfo[i].
10020 ucSTAId,
10021 WLAN_CLIENT_DISCONNECT,
10022 mac);
10023 }
10024 hddLog(LOG1,
10025 FL("Delete STA with MAC::"
10026 MAC_ADDRESS_STR),
10027 MAC_ADDR_ARRAY(mac));
10028
10029 if (pHddCtx->dev_dfs_cac_status ==
10030 DFS_CAC_IN_PROGRESS)
10031 goto fn_end;
10032
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010033 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010034 hdd_softap_sta_disassoc(pAdapter,
10035 mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010036 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010037 hdd_softap_sta_deauth(pAdapter,
10038 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010039 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010040 pAdapter->aStaInfo[i].
10041 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010042 qdf_status =
10043 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010044 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010045 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010046 if (!QDF_IS_STATUS_SUCCESS(
10047 qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010048 hddLog(LOGE,
10049 "%s: Deauth wait time expired",
10050 __func__);
10051 }
10052 }
10053 }
10054 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010055 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010057 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010058 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010059 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010060 hddLog(LOG1,
10061 FL("Skip DEL STA as this is not used::"
10062 MAC_ADDRESS_STR),
10063 MAC_ADDR_ARRAY(mac));
10064 return -ENOENT;
10065 }
10066
10067 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
10068 hdd_ipa_wlan_evt(pAdapter, staId,
10069 WLAN_CLIENT_DISCONNECT, mac);
10070 }
10071
10072 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
10073 true) {
10074 hddLog(LOG1,
10075 FL("Skip DEL STA as deauth is in progress::"
10076 MAC_ADDRESS_STR),
10077 MAC_ADDR_ARRAY(mac));
10078 return -ENOENT;
10079 }
10080
10081 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
10082
10083 hddLog(LOG1,
10084 FL("Delete STA with MAC::" MAC_ADDRESS_STR),
10085 MAC_ADDR_ARRAY(mac));
10086
10087 /* Case: SAP in ACS selected DFS ch and client connected
10088 * Now Radar detected. Then if random channel is another
10089 * DFS ch then new CAC is initiated and no TX allowed.
10090 * So do not send any mgmt frames as it will timeout
10091 * during CAC.
10092 */
10093
10094 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
10095 goto fn_end;
10096
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010097 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010098 hdd_softap_sta_disassoc(pAdapter, mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010099 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010100 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010101 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102 pAdapter->aStaInfo[staId].isDeauthInProgress =
10103 false;
10104 hddLog(LOG1,
10105 FL("STA removal failed for ::"
10106 MAC_ADDRESS_STR),
10107 MAC_ADDR_ARRAY(mac));
10108 return -ENOENT;
10109 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010110 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010111 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010112 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010113 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114 hddLog(LOGE,
10115 "%s: Deauth wait time expired",
10116 __func__);
10117 }
10118 }
10119 }
10120
10121fn_end:
10122 EXIT();
10123 return 0;
10124}
10125
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010126#if defined(USE_CFG80211_DEL_STA_V2)
10127/**
10128 * wlan_hdd_del_station() - delete station wrapper
10129 * @adapter: pointer to the hdd adapter
10130 *
10131 * Return: None
10132 */
10133void wlan_hdd_del_station(hdd_adapter_t *adapter)
10134{
10135 struct station_del_parameters del_sta;
10136 del_sta.mac = NULL;
10137 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10138 del_sta.reason_code = eCsrForcedDeauthSta;
10139
10140 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
10141 &del_sta);
10142}
10143#else
10144void wlan_hdd_del_station(hdd_adapter_t *adapter)
10145{
10146 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
10147}
10148#endif
10149
10150#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151/**
10152 * wlan_hdd_cfg80211_del_station() - delete station v2
10153 * @wiphy: Pointer to wiphy
10154 * @param: Pointer to delete station parameter
10155 *
10156 * Return: 0 for success, non-zero for failure
10157 */
10158int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10159 struct net_device *dev,
10160 struct station_del_parameters *param)
10161#else
10162/**
10163 * wlan_hdd_cfg80211_del_station() - delete station
10164 * @wiphy: Pointer to wiphy
10165 * @mac: Pointer to station mac address
10166 *
10167 * Return: 0 for success, non-zero for failure
10168 */
10169#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10170int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10171 struct net_device *dev,
10172 const uint8_t *mac)
10173#else
10174int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10175 struct net_device *dev,
10176 uint8_t *mac)
10177#endif
10178#endif
10179{
10180 int ret;
10181 struct tagCsrDelStaParams delStaParams;
10182
10183 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010184#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010186 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 return -EINVAL;
10188 }
10189 wlansap_populate_del_sta_params(param->mac, param->reason_code,
10190 param->subtype, &delStaParams);
10191#else
10192 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
10193 (SIR_MAC_MGMT_DEAUTH >> 4),
10194 &delStaParams);
10195#endif
10196 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
10197 cds_ssr_unprotect(__func__);
10198
10199 return ret;
10200}
10201
10202/**
10203 * __wlan_hdd_cfg80211_add_station() - add station
10204 * @wiphy: Pointer to wiphy
10205 * @mac: Pointer to station mac address
10206 * @pmksa: Pointer to add station parameter
10207 *
10208 * Return: 0 for success, non-zero for failure
10209 */
10210static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10211 struct net_device *dev,
10212 const uint8_t *mac,
10213 struct station_parameters *params)
10214{
10215 int status = -EPERM;
10216#ifdef FEATURE_WLAN_TDLS
10217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10218 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10219 u32 mask, set;
10220
10221 ENTER();
10222
Anurag Chouhan6d760662016-02-20 16:05:43 +053010223 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10225 return -EINVAL;
10226 }
10227
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010228 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229 TRACE_CODE_HDD_CFG80211_ADD_STA,
10230 pAdapter->sessionId, params->listen_interval));
10231
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010232 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010233 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010234
10235 mask = params->sta_flags_mask;
10236
10237 set = params->sta_flags_set;
10238
10239 hddLog(LOG1, FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), mask, set,
10240 MAC_ADDR_ARRAY(mac));
10241
10242 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10243 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
10244 status =
10245 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
10246 }
10247 }
10248#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010249 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250 return status;
10251}
10252
10253/**
10254 * wlan_hdd_cfg80211_add_station() - add station
10255 * @wiphy: Pointer to wiphy
10256 * @mac: Pointer to station mac address
10257 * @pmksa: Pointer to add station parameter
10258 *
10259 * Return: 0 for success, non-zero for failure
10260 */
10261#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10262static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10263 struct net_device *dev,
10264 const uint8_t *mac,
10265 struct station_parameters *params)
10266#else
10267static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
10268 struct net_device *dev, uint8_t *mac,
10269 struct station_parameters *params)
10270#endif
10271{
10272 int ret;
10273
10274 cds_ssr_protect(__func__);
10275 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
10276 cds_ssr_unprotect(__func__);
10277
10278 return ret;
10279}
10280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010281/**
10282 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
10283 * @wiphy: Pointer to wiphy
10284 * @dev: Pointer to network device
10285 * @pmksa: Pointer to set pmksa parameter
10286 *
10287 * Return: 0 for success, non-zero for failure
10288 */
10289static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10290 struct net_device *dev,
10291 struct cfg80211_pmksa *pmksa)
10292{
10293 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10294 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10295 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010296 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010297 int status;
10298 tPmkidCacheInfo pmk_id;
10299
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010300 ENTER();
10301
Anurag Chouhan6d760662016-02-20 16:05:43 +053010302 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010303 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10304 return -EINVAL;
10305 }
10306
10307 if (!pmksa) {
10308 hddLog(LOGE, FL("pmksa is NULL"));
10309 return -EINVAL;
10310 }
10311
10312 if (!pmksa->bssid || !pmksa->pmkid) {
10313 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
10314 pmksa->bssid, pmksa->pmkid);
10315 return -EINVAL;
10316 }
10317
10318 hddLog(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR),
10319 MAC_ADDR_ARRAY(pmksa->bssid));
10320
10321 status = wlan_hdd_validate_context(pHddCtx);
10322
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010323 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010325
10326 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10327
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010328 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
10329 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010330
10331 /* Add to the PMKSA ID Cache in CSR */
10332 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
10333 &pmk_id, 1, false);
10334
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010335 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010336 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
10337 pAdapter->sessionId, result));
10338
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010339 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010340 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010341}
10342
10343/**
10344 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
10345 * @wiphy: Pointer to wiphy
10346 * @dev: Pointer to network device
10347 * @pmksa: Pointer to set pmksa parameter
10348 *
10349 * Return: 0 for success, non-zero for failure
10350 */
10351static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
10352 struct net_device *dev,
10353 struct cfg80211_pmksa *pmksa)
10354{
10355 int ret;
10356
10357 cds_ssr_protect(__func__);
10358 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
10359 cds_ssr_unprotect(__func__);
10360
10361 return ret;
10362}
10363
10364/**
10365 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10366 * @wiphy: Pointer to wiphy
10367 * @dev: Pointer to network device
10368 * @pmksa: Pointer to pmksa parameter
10369 *
10370 * Return: 0 for success, non-zero for failure
10371 */
10372static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10373 struct net_device *dev,
10374 struct cfg80211_pmksa *pmksa)
10375{
10376 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10377 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10378 tHalHandle halHandle;
10379 int status = 0;
10380
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010381 ENTER();
10382
Anurag Chouhan6d760662016-02-20 16:05:43 +053010383 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010384 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10385 return -EINVAL;
10386 }
10387
10388 if (!pmksa) {
10389 hddLog(LOGE, FL("pmksa is NULL"));
10390 return -EINVAL;
10391 }
10392
10393 if (!pmksa->bssid) {
10394 hddLog(LOGE, FL("pmksa->bssid is NULL"));
10395 return -EINVAL;
10396 }
10397
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010398 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010399 MAC_ADDR_ARRAY(pmksa->bssid));
10400
10401 status = wlan_hdd_validate_context(pHddCtx);
10402
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010403 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010405
10406 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10407
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010408 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010409 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
10410 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010412 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010413 sme_roam_del_pmkid_from_cache(halHandle,
10414 pAdapter->sessionId, pmksa->bssid,
10415 false)) {
10416 hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR),
10417 MAC_ADDR_ARRAY(pmksa->bssid));
10418 status = -EINVAL;
10419 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010420 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010421 return status;
10422}
10423
10424/**
10425 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
10426 * @wiphy: Pointer to wiphy
10427 * @dev: Pointer to network device
10428 * @pmksa: Pointer to pmksa parameter
10429 *
10430 * Return: 0 for success, non-zero for failure
10431 */
10432static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
10433 struct net_device *dev,
10434 struct cfg80211_pmksa *pmksa)
10435{
10436 int ret;
10437
10438 cds_ssr_protect(__func__);
10439 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
10440 cds_ssr_unprotect(__func__);
10441
10442 return ret;
10443
10444}
10445
10446/**
10447 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10448 * @wiphy: Pointer to wiphy
10449 * @dev: Pointer to network device
10450 *
10451 * Return: 0 for success, non-zero for failure
10452 */
10453static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10454 struct net_device *dev)
10455{
10456 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10457 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10458 tHalHandle halHandle;
10459 int status = 0;
10460
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010461 ENTER();
10462
Anurag Chouhan6d760662016-02-20 16:05:43 +053010463 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010464 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10465 return -EINVAL;
10466 }
10467
10468 hddLog(LOGW, FL("Flushing PMKSA"));
10469
10470 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10471 status = wlan_hdd_validate_context(pHddCtx);
10472
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010473 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010475
10476 /* Retrieve halHandle */
10477 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10478
10479 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010480 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010481 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
10482 true)) {
10483 hddLog(LOGE, FL("Cannot flush PMKIDCache"));
10484 status = -EINVAL;
10485 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010486 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487 return status;
10488}
10489
10490/**
10491 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
10492 * @wiphy: Pointer to wiphy
10493 * @dev: Pointer to network device
10494 *
10495 * Return: 0 for success, non-zero for failure
10496 */
10497static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
10498 struct net_device *dev)
10499{
10500 int ret;
10501
10502 cds_ssr_protect(__func__);
10503 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
10504 cds_ssr_unprotect(__func__);
10505
10506 return ret;
10507}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010508
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080010509#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010510/**
10511 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
10512 * @wiphy: Pointer to wiphy
10513 * @dev: Pointer to network device
10514 * @ftie: Pointer to fast transition ie parameter
10515 *
10516 * Return: 0 for success, non-zero for failure
10517 */
10518static int
10519__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
10520 struct net_device *dev,
10521 struct cfg80211_update_ft_ies_params *ftie)
10522{
10523 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
10524 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10525 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10526 int status;
10527
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010528 ENTER();
10529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010530 status = wlan_hdd_validate_context(hdd_ctx);
10531 if (status)
10532 return status;
10533
Anurag Chouhan6d760662016-02-20 16:05:43 +053010534 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010535 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10536 return -EINVAL;
10537 }
10538
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010539 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010540 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
10541 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
10542 /* Added for debug on reception of Re-assoc Req. */
10543 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
10544 hddLog(LOGE,
10545 FL("Called with Ie of length = %zu when not associated"),
10546 ftie->ie_len);
10547 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
10548 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549 hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__,
10550 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010551
10552 /* Pass the received FT IEs to SME */
10553 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
10554 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010555 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556 return 0;
10557}
10558
10559/**
10560 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
10561 * @wiphy: Pointer to wiphy
10562 * @dev: Pointer to network device
10563 * @ftie: Pointer to fast transition ie parameter
10564 *
10565 * Return: 0 for success, non-zero for failure
10566 */
10567static int
10568wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
10569 struct net_device *dev,
10570 struct cfg80211_update_ft_ies_params *ftie)
10571{
10572 int ret;
10573
10574 cds_ssr_protect(__func__);
10575 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
10576 cds_ssr_unprotect(__func__);
10577
10578 return ret;
10579}
10580#endif
10581
10582#ifdef WLAN_FEATURE_GTK_OFFLOAD
10583/**
10584 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
10585 * @callbackContext: Callback context
10586 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
10587 *
10588 * Callback rountine called upon receiving response for get offload info
10589 *
10590 * Return: none
10591 */
10592void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
10593 tpSirGtkOffloadGetInfoRspParams
10594 pGtkOffloadGetInfoRsp)
10595{
10596 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
10597 uint8_t tempReplayCounter[8];
10598 hdd_station_ctx_t *pHddStaCtx;
10599
10600 ENTER();
10601
10602 if (NULL == pAdapter) {
10603 hddLog(LOGE, FL("HDD adapter is Null"));
10604 return;
10605 }
10606
10607 if (NULL == pGtkOffloadGetInfoRsp) {
10608 hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null"));
10609 return;
10610 }
10611
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010612 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010613 hddLog(LOGE, FL("wlan Failed to get replay counter value"));
10614 return;
10615 }
10616
10617 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10618 /* Update replay counter */
10619 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
10620 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
10621
10622 {
10623 /* changing from little to big endian since supplicant
10624 * works on big endian format
10625 */
10626 int i;
10627 uint8_t *p =
10628 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
10629
10630 for (i = 0; i < 8; i++) {
10631 tempReplayCounter[7 - i] = (uint8_t) p[i];
10632 }
10633 }
10634
10635 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080010636 cfg80211_gtk_rekey_notify(pAdapter->dev,
10637 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638 tempReplayCounter, GFP_KERNEL);
10639}
10640
10641/**
10642 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10643 * @wiphy: Pointer to wiphy
10644 * @dev: Pointer to network device
10645 * @data: Pointer to rekey data
10646 *
10647 * This function is used to offload GTK rekeying job to the firmware.
10648 *
10649 * Return: 0 for success, non-zero for failure
10650 */
10651int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10652 struct net_device *dev,
10653 struct cfg80211_gtk_rekey_data *data)
10654{
10655 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10656 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10657 hdd_station_ctx_t *pHddStaCtx;
10658 tHalHandle hHal;
10659 int result;
10660 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010661 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010662
10663 ENTER();
10664
Anurag Chouhan6d760662016-02-20 16:05:43 +053010665 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010666 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10667 return -EINVAL;
10668 }
10669
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010670 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
10672 pAdapter->sessionId, pAdapter->device_mode));
10673
10674 result = wlan_hdd_validate_context(pHddCtx);
10675
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010676 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010677 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010678
10679 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10680 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10681 if (NULL == hHal) {
10682 hddLog(LOGE, FL("HAL context is Null!!!"));
10683 return -EAGAIN;
10684 }
10685
10686 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
10687 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
10688 NL80211_KCK_LEN);
10689 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
10690 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053010691 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080010692 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010693 {
10694 /* changing from big to little endian since driver
10695 * works on little endian format
10696 */
10697 uint8_t *p =
10698 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
10699 ullKeyReplayCounter;
10700 int i;
10701
10702 for (i = 0; i < 8; i++) {
10703 p[7 - i] = data->replay_ctr[i];
10704 }
10705 }
10706
10707 if (true == pHddCtx->hdd_wlan_suspended) {
10708 /* if wlan is suspended, enable GTK offload directly from here */
10709 memcpy(&hddGtkOffloadReqParams,
10710 &pHddStaCtx->gtkOffloadReqParams,
10711 sizeof(tSirGtkOffloadParams));
10712 status =
10713 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
10714 pAdapter->sessionId);
10715
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010716 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010717 hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"),
10718 status);
10719 return -EINVAL;
10720 }
10721 hddLog(LOG1, FL("sme_set_gtk_offload successful"));
10722 } else {
10723 hddLog(LOG1,
10724 FL("wlan not suspended GTKOffload request is stored"));
10725 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010726 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010727 return result;
10728}
10729
10730/**
10731 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10732 * @wiphy: Pointer to wiphy
10733 * @dev: Pointer to network device
10734 * @data: Pointer to rekey data
10735 *
10736 * This function is used to offload GTK rekeying job to the firmware.
10737 *
10738 * Return: 0 for success, non-zero for failure
10739 */
10740int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10741 struct net_device *dev,
10742 struct cfg80211_gtk_rekey_data *data)
10743{
10744 int ret;
10745
10746 cds_ssr_protect(__func__);
10747 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
10748 cds_ssr_unprotect(__func__);
10749
10750 return ret;
10751}
10752#endif /*WLAN_FEATURE_GTK_OFFLOAD */
10753
10754/**
10755 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
10756 * @wiphy: Pointer to wiphy
10757 * @dev: Pointer to network device
10758 * @param: Pointer to access control parameter
10759 *
10760 * Return: 0 for success, non-zero for failure
10761 */
10762static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10763 struct net_device *dev,
10764 const struct cfg80211_acl_data *params)
10765{
10766 int i;
10767 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10768 hdd_hostapd_state_t *pHostapdState;
10769 tsap_Config_t *pConfig;
10770 v_CONTEXT_t p_cds_context = NULL;
10771 hdd_context_t *pHddCtx;
10772 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010773 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774
10775 ENTER();
10776
Anurag Chouhan6d760662016-02-20 16:05:43 +053010777 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010778 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10779 return -EINVAL;
10780 }
10781
10782 if (NULL == params) {
10783 hddLog(LOGE, FL("params is Null"));
10784 return -EINVAL;
10785 }
10786
10787 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10788 status = wlan_hdd_validate_context(pHddCtx);
10789
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010790 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010791 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792
10793 p_cds_context = pHddCtx->pcds_context;
10794 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10795
10796 if (NULL == pHostapdState) {
10797 hddLog(LOGE, FL("pHostapdState is Null"));
10798 return -EINVAL;
10799 }
10800
10801 hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy,
10802 params->n_acl_entries);
10803
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010804 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010805 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
10806 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080010807 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
10809
10810 /* default value */
10811 pConfig->num_accept_mac = 0;
10812 pConfig->num_deny_mac = 0;
10813
10814 /**
10815 * access control policy
10816 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
10817 * listed in hostapd.deny file.
10818 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
10819 * listed in hostapd.accept file.
10820 */
10821 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
10822 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
10823 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
10824 params->acl_policy) {
10825 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
10826 } else {
10827 hddLog(LOGE, FL("Acl Policy : %d is not supported"),
10828 params->acl_policy);
10829 return -ENOTSUPP;
10830 }
10831
10832 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
10833 pConfig->num_accept_mac = params->n_acl_entries;
10834 for (i = 0; i < params->n_acl_entries; i++) {
10835 hddLog(LOG1,
10836 FL("** Add ACL MAC entry %i in WhiletList :"
10837 MAC_ADDRESS_STR), i,
10838 MAC_ADDR_ARRAY(
10839 params->mac_addrs[i].addr));
10840
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010841 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842 params->mac_addrs[i].addr,
10843 sizeof(qcmacaddr));
10844 }
10845 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
10846 pConfig->num_deny_mac = params->n_acl_entries;
10847 for (i = 0; i < params->n_acl_entries; i++) {
10848 hddLog(LOG1,
10849 FL("** Add ACL MAC entry %i in BlackList :"
10850 MAC_ADDRESS_STR), i,
10851 MAC_ADDR_ARRAY(
10852 params->mac_addrs[i].addr));
10853
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010854 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 params->mac_addrs[i].addr,
10856 sizeof(qcmacaddr));
10857 }
10858 }
10859#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010860 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
10862 pConfig);
10863#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010864 qdf_status = wlansap_set_mac_acl(p_cds_context, pConfig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010866 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010867 hddLog(LOGE, FL("SAP Set Mac Acl fail"));
10868 return -EINVAL;
10869 }
10870 } else {
10871 hddLog(LOG1, FL("Invalid device_mode %s(%d)"),
10872 hdd_device_mode_to_string(pAdapter->device_mode),
10873 pAdapter->device_mode);
10874 return -EINVAL;
10875 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010876 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877 return 0;
10878}
10879
10880/**
10881 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
10882 * __wlan_hdd_cfg80211_set_mac_acl
10883 * @wiphy: pointer to wiphy structure
10884 * @dev: pointer to net_device
10885 * @params: pointer to cfg80211_acl_data
10886 *
10887 * Return; 0 on success, error number otherwise
10888 */
10889static int
10890wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10891 struct net_device *dev,
10892 const struct cfg80211_acl_data *params)
10893{
10894 int ret;
10895
10896 cds_ssr_protect(__func__);
10897 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
10898 cds_ssr_unprotect(__func__);
10899
10900 return ret;
10901}
10902
10903#ifdef WLAN_NL80211_TESTMODE
10904#ifdef FEATURE_WLAN_LPHB
10905/**
10906 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
10907 * @pHddCtx: Pointer to hdd context
10908 * @lphbInd: Pointer to low power heart beat indication parameter
10909 *
10910 * Return: none
10911 */
10912void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
10913{
10914 struct sk_buff *skb;
10915
10916 hddLog(LOGE, FL("LPHB indication arrived"));
10917
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010918 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920
10921 if (NULL == lphbInd) {
10922 hddLog(LOGE, FL("invalid argument lphbInd"));
10923 return;
10924 }
10925
10926 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
10927 wiphy, sizeof(tSirLPHBInd),
10928 GFP_ATOMIC);
10929 if (!skb) {
10930 hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail"));
10931 return;
10932 }
10933
10934 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
10935 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail"));
10936 goto nla_put_failure;
10937 }
10938 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
10939 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail"));
10940 goto nla_put_failure;
10941 }
10942 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
10943 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail"));
10944 goto nla_put_failure;
10945 }
10946 cfg80211_testmode_event(skb, GFP_ATOMIC);
10947 return;
10948
10949nla_put_failure:
10950 hddLog(LOGE, FL("NLA Put fail"));
10951 kfree_skb(skb);
10952
10953 return;
10954}
10955#endif /* FEATURE_WLAN_LPHB */
10956
10957/**
10958 * __wlan_hdd_cfg80211_testmode() - test mode
10959 * @wiphy: Pointer to wiphy
10960 * @data: Data pointer
10961 * @len: Data length
10962 *
10963 * Return: 0 for success, non-zero for failure
10964 */
10965static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10966 void *data, int len)
10967{
10968 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
10969 int err;
10970 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10971
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010972 ENTER();
10973
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 err = wlan_hdd_validate_context(pHddCtx);
10975 if (err)
10976 return err;
10977
10978 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
10979 len, wlan_hdd_tm_policy);
10980 if (err) {
10981 hddLog(LOGE, FL("Testmode INV ATTR"));
10982 return err;
10983 }
10984
10985 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
10986 hddLog(LOGE, FL("Testmode INV CMD"));
10987 return -EINVAL;
10988 }
10989
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010990 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053010991 TRACE_CODE_HDD_CFG80211_TESTMODE,
10992 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
10994#ifdef FEATURE_WLAN_LPHB
10995 /* Low Power Heartbeat configuration request */
10996 case WLAN_HDD_TM_CMD_WLAN_HB:
10997 {
10998 int buf_len;
10999 void *buf;
11000 tSirLPHBReq *hb_params = NULL;
11001 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011002 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011003
11004 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
11005 hddLog(LOGE, FL("Testmode INV DATA"));
11006 return -EINVAL;
11007 }
11008
11009 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
11010 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
11011
11012 hb_params_temp = (tSirLPHBReq *) buf;
11013 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
11014 && (hb_params_temp->params.lphbTcpParamReq.
11015 timePeriodSec == 0))
11016 return -EINVAL;
11017
11018 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011019 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 if (NULL == hb_params) {
11021 hddLog(LOGE, FL("Request Buffer Alloc Fail"));
11022 return -ENOMEM;
11023 }
11024
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011025 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 smeStatus =
11027 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
11028 hb_params,
11029 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011030 if (QDF_STATUS_SUCCESS != smeStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011031 hddLog(LOGE, "LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011032 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033 }
11034 return 0;
11035 }
11036#endif /* FEATURE_WLAN_LPHB */
11037
11038#if defined(QCA_WIFI_FTM)
11039 case WLAN_HDD_TM_CMD_WLAN_FTM:
11040 {
11041 int buf_len;
11042 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011043 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
11045 hddLog(LOGE,
11046 FL
11047 ("WLAN_HDD_TM_ATTR_DATA attribute is invalid"));
11048 return -EINVAL;
11049 }
11050
11051 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
11052 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
11053
11054 pr_info("****FTM Tx cmd len = %d*****\n", buf_len);
11055
11056 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
11057
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011058 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 err = -EBUSY;
11060 break;
11061 }
11062#endif
11063
11064 default:
11065 hddLog(LOGE, FL("command %d not supported"),
11066 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
11067 return -EOPNOTSUPP;
11068 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011069 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 return err;
11071}
11072
11073/**
11074 * wlan_hdd_cfg80211_testmode() - test mode
11075 * @wiphy: Pointer to wiphy
11076 * @dev: Pointer to network device
11077 * @data: Data pointer
11078 * @len: Data length
11079 *
11080 * Return: 0 for success, non-zero for failure
11081 */
11082static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
11083#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11084 struct wireless_dev *wdev,
11085#endif
11086 void *data, int len)
11087{
11088 int ret;
11089
11090 cds_ssr_protect(__func__);
11091 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
11092 cds_ssr_unprotect(__func__);
11093
11094 return ret;
11095}
11096
11097#if defined(QCA_WIFI_FTM)
11098/**
11099 * wlan_hdd_testmode_rx_event() - test mode rx event handler
11100 * @buf: Pointer to buffer
11101 * @buf_len: Buffer length
11102 *
11103 * Return: none
11104 */
11105void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
11106{
11107 struct sk_buff *skb;
11108 hdd_context_t *hdd_ctx;
11109
11110 if (!buf || !buf_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011111 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011112 "%s: buf or buf_len invalid, buf = %p buf_len = %zu",
11113 __func__, buf, buf_len);
11114 return;
11115 }
11116
Anurag Chouhan6d760662016-02-20 16:05:43 +053011117 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011119 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120 "%s: hdd context invalid", __func__);
11121 return;
11122 }
11123
11124 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
11125 buf_len, GFP_KERNEL);
11126 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011127 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 "%s: failed to allocate testmode rx skb!", __func__);
11129 return;
11130 }
11131
11132 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
11133 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
11134 goto nla_put_failure;
11135
11136 pr_info("****FTM Rx cmd len = %zu*****\n", buf_len);
11137
11138 cfg80211_testmode_event(skb, GFP_KERNEL);
11139 return;
11140
11141nla_put_failure:
11142 kfree_skb(skb);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011143 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 "%s: nla_put failed on testmode rx skb!", __func__);
11145}
11146#endif
11147#endif /* CONFIG_NL80211_TESTMODE */
11148
11149#ifdef QCA_HT_2040_COEX
11150/**
11151 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11152 * @wiphy: Pointer to wiphy
11153 * @dev: Pointer to network device
11154 * @chandef: Pointer to channel definition parameter
11155 *
11156 * Return: 0 for success, non-zero for failure
11157 */
11158static int
11159__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11160 struct net_device *dev,
11161 struct cfg80211_chan_def *chandef)
11162{
11163 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11164 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011165 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 tSmeConfigParams sme_config;
11167 bool cbModeChange;
11168
Anurag Chouhan6d760662016-02-20 16:05:43 +053011169 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11171 return -EINVAL;
11172 }
11173
11174 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11175 status = wlan_hdd_validate_context(pHddCtx);
11176
11177 if (0 != status) {
11178 hddLog(LOGE, FL("HDD context is not valid"));
11179 return status;
11180 }
11181
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011182 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011183 sme_get_config_param(pHddCtx->hHal, &sme_config);
11184 switch (chandef->width) {
11185 case NL80211_CHAN_WIDTH_20:
11186 if (sme_config.csrConfig.channelBondingMode24GHz !=
11187 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11188 sme_config.csrConfig.channelBondingMode24GHz =
11189 eCSR_INI_SINGLE_CHANNEL_CENTERED;
11190 sme_update_config(pHddCtx->hHal, &sme_config);
11191 cbModeChange = true;
11192 }
11193 break;
11194
11195 case NL80211_CHAN_WIDTH_40:
11196 if (sme_config.csrConfig.channelBondingMode24GHz ==
11197 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
11198 if (NL80211_CHAN_HT40MINUS ==
11199 cfg80211_get_chandef_type(chandef))
11200 sme_config.csrConfig.channelBondingMode24GHz =
11201 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
11202 else
11203 sme_config.csrConfig.channelBondingMode24GHz =
11204 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
11205 sme_update_config(pHddCtx->hHal, &sme_config);
11206 cbModeChange = true;
11207 }
11208 break;
11209
11210 default:
11211 hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !"));
11212 return -EINVAL;
11213 }
11214
11215 if (!cbModeChange)
11216 return 0;
11217
Krunal Sonib4326f22016-03-10 13:05:51 -080011218 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219 return 0;
11220
11221 hddLog(LOG1, FL("Channel bonding changed to %d"),
11222 sme_config.csrConfig.channelBondingMode24GHz);
11223
11224 /* Change SAP ht2040 mode */
11225 status = hdd_set_sap_ht2040_mode(pAdapter,
11226 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011227 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011228 hddLog(LOGE, FL("Error!!! Cannot set SAP HT20/40 mode!"));
11229 return -EINVAL;
11230 }
11231
11232 return 0;
11233}
11234
11235/**
11236 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11237 * @wiphy: Pointer to wiphy
11238 * @dev: Pointer to network device
11239 * @chandef: Pointer to channel definition parameter
11240 *
11241 * Return: 0 for success, non-zero for failure
11242 */
11243static int
11244wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11245 struct net_device *dev,
11246 struct cfg80211_chan_def *chandef)
11247{
11248 int ret;
11249
11250 cds_ssr_protect(__func__);
11251 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
11252 cds_ssr_unprotect(__func__);
11253
11254 return ret;
11255}
11256#endif
11257
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011258#ifdef CHANNEL_SWITCH_SUPPORTED
11259/**
11260 * __wlan_hdd_cfg80211_channel_switch()- function to switch
11261 * channel in SAP/GO
11262 * @wiphy: wiphy pointer
11263 * @dev: dev pointer.
11264 * @csa_params: Change channel params
11265 *
11266 * This function is called to switch channel in SAP/GO
11267 *
11268 * Return: 0 if success else return non zero
11269 */
11270static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11271 struct net_device *dev,
11272 struct cfg80211_csa_settings *csa_params)
11273{
11274 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
11275 hdd_context_t *hdd_ctx;
11276 uint8_t channel;
11277 uint16_t freq;
11278 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080011279 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011280
11281 hddLog(LOG1, FL("Set Freq %d"),
11282 csa_params->chandef.chan->center_freq);
11283
11284 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11285 ret = wlan_hdd_validate_context(hdd_ctx);
11286
11287 if (0 != ret)
11288 return ret;
11289
Krunal Sonib4326f22016-03-10 13:05:51 -080011290 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
11291 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011292 return -ENOTSUPP;
11293
11294 freq = csa_params->chandef.chan->center_freq;
11295 channel = cds_freq_to_chan(freq);
11296
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053011297 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
11298
11299 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011300 return ret;
11301}
11302
11303/**
11304 * wlan_hdd_cfg80211_channel_switch()- function to switch
11305 * channel in SAP/GO
11306 * @wiphy: wiphy pointer
11307 * @dev: dev pointer.
11308 * @csa_params: Change channel params
11309 *
11310 * This function is called to switch channel in SAP/GO
11311 *
11312 * Return: 0 if success else return non zero
11313 */
11314static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
11315 struct net_device *dev,
11316 struct cfg80211_csa_settings *csa_params)
11317{
11318 int ret;
11319
11320 cds_ssr_protect(__func__);
11321 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
11322 cds_ssr_unprotect(__func__);
11323 return ret;
11324}
11325#endif
11326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011327/**
11328 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
11329 * translation from NL to policy manager type
11330 * @type: Generic connection mode type defined in NL
11331 *
11332 *
11333 * This function provides the type translation
11334 *
11335 * Return: cds_con_mode enum
11336 */
11337enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
11338 enum nl80211_iftype type)
11339{
11340 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
11341 switch (type) {
11342 case NL80211_IFTYPE_STATION:
11343 mode = CDS_STA_MODE;
11344 break;
11345 case NL80211_IFTYPE_P2P_CLIENT:
11346 mode = CDS_P2P_CLIENT_MODE;
11347 break;
11348 case NL80211_IFTYPE_P2P_GO:
11349 mode = CDS_P2P_GO_MODE;
11350 break;
11351 case NL80211_IFTYPE_AP:
11352 mode = CDS_SAP_MODE;
11353 break;
11354 case NL80211_IFTYPE_ADHOC:
11355 mode = CDS_IBSS_MODE;
11356 break;
11357 default:
11358 hddLog(LOGE, FL("Unsupported interface type (%d)"),
11359 type);
11360 }
11361 return mode;
11362}
11363
11364/**
11365 * struct cfg80211_ops - cfg80211_ops
11366 *
11367 * @add_virtual_intf: Add virtual interface
11368 * @del_virtual_intf: Delete virtual interface
11369 * @change_virtual_intf: Change virtual interface
11370 * @change_station: Change station
11371 * @add_beacon: Add beacon in sap mode
11372 * @del_beacon: Delete beacon in sap mode
11373 * @set_beacon: Set beacon in sap mode
11374 * @start_ap: Start ap
11375 * @change_beacon: Change beacon
11376 * @stop_ap: Stop ap
11377 * @change_bss: Change bss
11378 * @add_key: Add key
11379 * @get_key: Get key
11380 * @del_key: Delete key
11381 * @set_default_key: Set default key
11382 * @set_channel: Set channel
11383 * @scan: Scan
11384 * @connect: Connect
11385 * @disconnect: Disconnect
11386 * @join_ibss = Join ibss
11387 * @leave_ibss = Leave ibss
11388 * @set_wiphy_params = Set wiphy params
11389 * @set_tx_power = Set tx power
11390 * @get_tx_power = get tx power
11391 * @remain_on_channel = Remain on channel
11392 * @cancel_remain_on_channel = Cancel remain on channel
11393 * @mgmt_tx = Tx management frame
11394 * @mgmt_tx_cancel_wait = Cancel management tx wait
11395 * @set_default_mgmt_key = Set default management key
11396 * @set_txq_params = Set tx queue parameters
11397 * @get_station = Get station
11398 * @set_power_mgmt = Set power management
11399 * @del_station = Delete station
11400 * @add_station = Add station
11401 * @set_pmksa = Set pmksa
11402 * @del_pmksa = Delete pmksa
11403 * @flush_pmksa = Flush pmksa
11404 * @update_ft_ies = Update FT IEs
11405 * @tdls_mgmt = Tdls management
11406 * @tdls_oper = Tdls operation
11407 * @set_rekey_data = Set rekey data
11408 * @sched_scan_start = Scheduled scan start
11409 * @sched_scan_stop = Scheduled scan stop
11410 * @resume = Resume wlan
11411 * @suspend = Suspend wlan
11412 * @set_mac_acl = Set mac acl
11413 * @testmode_cmd = Test mode command
11414 * @set_ap_chanwidth = Set AP channel bandwidth
11415 * @dump_survey = Dump survey
11416 * @key_mgmt_set_pmk = Set pmk key management
11417 */
11418static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
11419 .add_virtual_intf = wlan_hdd_add_virtual_intf,
11420 .del_virtual_intf = wlan_hdd_del_virtual_intf,
11421 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
11422 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011423 .start_ap = wlan_hdd_cfg80211_start_ap,
11424 .change_beacon = wlan_hdd_cfg80211_change_beacon,
11425 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011426 .change_bss = wlan_hdd_cfg80211_change_bss,
11427 .add_key = wlan_hdd_cfg80211_add_key,
11428 .get_key = wlan_hdd_cfg80211_get_key,
11429 .del_key = wlan_hdd_cfg80211_del_key,
11430 .set_default_key = wlan_hdd_cfg80211_set_default_key,
11431 .scan = wlan_hdd_cfg80211_scan,
11432 .connect = wlan_hdd_cfg80211_connect,
11433 .disconnect = wlan_hdd_cfg80211_disconnect,
11434 .join_ibss = wlan_hdd_cfg80211_join_ibss,
11435 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
11436 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
11437 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
11438 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
11439 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
11440 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
11441 .mgmt_tx = wlan_hdd_mgmt_tx,
11442 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
11443 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
11444 .set_txq_params = wlan_hdd_set_txq_params,
11445 .get_station = wlan_hdd_cfg80211_get_station,
11446 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
11447 .del_station = wlan_hdd_cfg80211_del_station,
11448 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011449 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
11450 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
11451 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080011452#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011453 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
11454#endif
11455#ifdef FEATURE_WLAN_TDLS
11456 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
11457 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
11458#endif
11459#ifdef WLAN_FEATURE_GTK_OFFLOAD
11460 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
11461#endif /* WLAN_FEATURE_GTK_OFFLOAD */
11462#ifdef FEATURE_WLAN_SCAN_PNO
11463 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
11464 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
11465#endif /*FEATURE_WLAN_SCAN_PNO */
11466 .resume = wlan_hdd_cfg80211_resume_wlan,
11467 .suspend = wlan_hdd_cfg80211_suspend_wlan,
11468 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
11469#ifdef WLAN_NL80211_TESTMODE
11470 .testmode_cmd = wlan_hdd_cfg80211_testmode,
11471#endif
11472#ifdef QCA_HT_2040_COEX
11473 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
11474#endif
11475 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011476#ifdef CHANNEL_SWITCH_SUPPORTED
11477 .channel_switch = wlan_hdd_cfg80211_channel_switch,
11478#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011479};