blob: d6a5143e8fc3eb50d366acf57539ae8fe1623539 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * 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>
44#include <cdf_trace.h>
45#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"
55#include "wlan_hdd_p2p.h"
56#include "wlan_hdd_cfg80211.h"
57#include "wlan_hdd_hostapd.h"
58#include "wlan_hdd_softap_tx_rx.h"
59#include "wlan_hdd_main.h"
60#include "wlan_hdd_power.h"
61#include "wlan_hdd_trace.h"
62#include "cdf_types.h"
63#include "cdf_trace.h"
64#include "cds_utils.h"
65#include "cds_sched.h"
66#include "wlan_hdd_scan.h"
67#include <qc_sap_ioctl.h>
68#include "wlan_hdd_tdls.h"
69#include "wlan_hdd_wmm.h"
70#include "wma_types.h"
71#include "wlan_hdd_misc.h"
72#include "wlan_hdd_nan.h"
73#include <wlan_hdd_ipa.h>
74#include "wlan_logging_sock_svc.h"
75
76#ifdef FEATURE_WLAN_EXTSCAN
77#include "wlan_hdd_ext_scan.h"
78#endif
79
80#ifdef WLAN_FEATURE_LINK_LAYER_STATS
81#include "wlan_hdd_stats.h"
82#endif
83#include "cds_concurrency.h"
84#include "qwlan_version.h"
85#include "wlan_hdd_memdump.h"
86
87#include "wlan_hdd_ocb.h"
88
89#define g_mode_rates_size (12)
90#define a_mode_rates_size (8)
91#define FREQ_BASE_80211G (2407)
92#define FREQ_BAND_DIFF_80211G (5)
93#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
94 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
95
96/*
97 * Android CTS verifier needs atleast this much wait time (in msec)
98 */
99#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
100
101/*
102 * Refer @tCfgProtection structure for definition of the bit map.
103 * below value is obtained by setting the following bit-fields.
104 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
105 */
106#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
107
108#define HDD2GHZCHAN(freq, chan, flag) { \
109 .band = IEEE80211_BAND_2GHZ, \
110 .center_freq = (freq), \
111 .hw_value = (chan), \
112 .flags = (flag), \
113 .max_antenna_gain = 0, \
114 .max_power = 30, \
115}
116
117#define HDD5GHZCHAN(freq, chan, flag) { \
118 .band = IEEE80211_BAND_5GHZ, \
119 .center_freq = (freq), \
120 .hw_value = (chan), \
121 .flags = (flag), \
122 .max_antenna_gain = 0, \
123 .max_power = 30, \
124}
125
126#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
127 { \
128 .bitrate = rate, \
129 .hw_value = rate_id, \
130 .flags = flag, \
131 }
132
133#ifdef WLAN_FEATURE_VOWIFI_11R
134#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
135#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
136#endif
137
138#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139
140static const u32 hdd_cipher_suites[] = {
141 WLAN_CIPHER_SUITE_WEP40,
142 WLAN_CIPHER_SUITE_WEP104,
143 WLAN_CIPHER_SUITE_TKIP,
144#ifdef FEATURE_WLAN_ESE
145#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
146#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
147 WLAN_CIPHER_SUITE_BTK,
148 WLAN_CIPHER_SUITE_KRK,
149 WLAN_CIPHER_SUITE_CCMP,
150#else
151 WLAN_CIPHER_SUITE_CCMP,
152#endif
153#ifdef FEATURE_WLAN_WAPI
154 WLAN_CIPHER_SUITE_SMS4,
155#endif
156#ifdef WLAN_FEATURE_11W
157 WLAN_CIPHER_SUITE_AES_CMAC,
158#endif
159};
160
161static struct ieee80211_channel hdd_channels_2_4_ghz[] = {
162 HDD2GHZCHAN(2412, 1, 0),
163 HDD2GHZCHAN(2417, 2, 0),
164 HDD2GHZCHAN(2422, 3, 0),
165 HDD2GHZCHAN(2427, 4, 0),
166 HDD2GHZCHAN(2432, 5, 0),
167 HDD2GHZCHAN(2437, 6, 0),
168 HDD2GHZCHAN(2442, 7, 0),
169 HDD2GHZCHAN(2447, 8, 0),
170 HDD2GHZCHAN(2452, 9, 0),
171 HDD2GHZCHAN(2457, 10, 0),
172 HDD2GHZCHAN(2462, 11, 0),
173 HDD2GHZCHAN(2467, 12, 0),
174 HDD2GHZCHAN(2472, 13, 0),
175 HDD2GHZCHAN(2484, 14, 0),
176};
177
178static struct ieee80211_channel hdd_social_channels_2_4_ghz[] = {
179 HDD2GHZCHAN(2412, 1, 0),
180 HDD2GHZCHAN(2437, 6, 0),
181 HDD2GHZCHAN(2462, 11, 0),
182};
183
184static struct ieee80211_channel hdd_channels_5_ghz[] = {
185 HDD5GHZCHAN(4920, 240, 0),
186 HDD5GHZCHAN(4940, 244, 0),
187 HDD5GHZCHAN(4960, 248, 0),
188 HDD5GHZCHAN(4980, 252, 0),
189 HDD5GHZCHAN(5040, 208, 0),
190 HDD5GHZCHAN(5060, 212, 0),
191 HDD5GHZCHAN(5080, 216, 0),
192 HDD5GHZCHAN(5180, 36, 0),
193 HDD5GHZCHAN(5200, 40, 0),
194 HDD5GHZCHAN(5220, 44, 0),
195 HDD5GHZCHAN(5240, 48, 0),
196 HDD5GHZCHAN(5260, 52, 0),
197 HDD5GHZCHAN(5280, 56, 0),
198 HDD5GHZCHAN(5300, 60, 0),
199 HDD5GHZCHAN(5320, 64, 0),
200 HDD5GHZCHAN(5500, 100, 0),
201 HDD5GHZCHAN(5520, 104, 0),
202 HDD5GHZCHAN(5540, 108, 0),
203 HDD5GHZCHAN(5560, 112, 0),
204 HDD5GHZCHAN(5580, 116, 0),
205 HDD5GHZCHAN(5600, 120, 0),
206 HDD5GHZCHAN(5620, 124, 0),
207 HDD5GHZCHAN(5640, 128, 0),
208 HDD5GHZCHAN(5660, 132, 0),
209 HDD5GHZCHAN(5680, 136, 0),
210 HDD5GHZCHAN(5700, 140, 0),
211 HDD5GHZCHAN(5720, 144, 0),
212 HDD5GHZCHAN(5745, 149, 0),
213 HDD5GHZCHAN(5765, 153, 0),
214 HDD5GHZCHAN(5785, 157, 0),
215 HDD5GHZCHAN(5805, 161, 0),
216 HDD5GHZCHAN(5825, 165, 0),
217#ifndef FEATURE_STATICALLY_ADD_11P_CHANNELS
218 HDD5GHZCHAN(5852, 170, 0),
219 HDD5GHZCHAN(5855, 171, 0),
220 HDD5GHZCHAN(5860, 172, 0),
221 HDD5GHZCHAN(5865, 173, 0),
222 HDD5GHZCHAN(5870, 174, 0),
223 HDD5GHZCHAN(5875, 175, 0),
224 HDD5GHZCHAN(5880, 176, 0),
225 HDD5GHZCHAN(5885, 177, 0),
226 HDD5GHZCHAN(5890, 178, 0),
227 HDD5GHZCHAN(5895, 179, 0),
228 HDD5GHZCHAN(5900, 180, 0),
229 HDD5GHZCHAN(5905, 181, 0),
230 HDD5GHZCHAN(5910, 182, 0),
231 HDD5GHZCHAN(5915, 183, 0),
232 HDD5GHZCHAN(5920, 184, 0),
233#endif
234};
235
236static struct ieee80211_rate g_mode_rates[] = {
237 HDD_G_MODE_RATETAB(10, 0x1, 0),
238 HDD_G_MODE_RATETAB(20, 0x2, 0),
239 HDD_G_MODE_RATETAB(55, 0x4, 0),
240 HDD_G_MODE_RATETAB(110, 0x8, 0),
241 HDD_G_MODE_RATETAB(60, 0x10, 0),
242 HDD_G_MODE_RATETAB(90, 0x20, 0),
243 HDD_G_MODE_RATETAB(120, 0x40, 0),
244 HDD_G_MODE_RATETAB(180, 0x80, 0),
245 HDD_G_MODE_RATETAB(240, 0x100, 0),
246 HDD_G_MODE_RATETAB(360, 0x200, 0),
247 HDD_G_MODE_RATETAB(480, 0x400, 0),
248 HDD_G_MODE_RATETAB(540, 0x800, 0),
249};
250
251static struct ieee80211_rate a_mode_rates[] = {
252 HDD_G_MODE_RATETAB(60, 0x10, 0),
253 HDD_G_MODE_RATETAB(90, 0x20, 0),
254 HDD_G_MODE_RATETAB(120, 0x40, 0),
255 HDD_G_MODE_RATETAB(180, 0x80, 0),
256 HDD_G_MODE_RATETAB(240, 0x100, 0),
257 HDD_G_MODE_RATETAB(360, 0x200, 0),
258 HDD_G_MODE_RATETAB(480, 0x400, 0),
259 HDD_G_MODE_RATETAB(540, 0x800, 0),
260};
261
262static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
263 .channels = hdd_channels_2_4_ghz,
264 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
265 .band = IEEE80211_BAND_2GHZ,
266 .bitrates = g_mode_rates,
267 .n_bitrates = g_mode_rates_size,
268 .ht_cap.ht_supported = 1,
269 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
270 | IEEE80211_HT_CAP_GRN_FLD
271 | IEEE80211_HT_CAP_DSSSCCK40
272 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
273 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
274 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
275 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
276 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
277 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
278 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
279};
280
281static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_ghz = {
282 .channels = hdd_social_channels_2_4_ghz,
283 .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_ghz),
284 .band = IEEE80211_BAND_2GHZ,
285 .bitrates = g_mode_rates,
286 .n_bitrates = g_mode_rates_size,
287 .ht_cap.ht_supported = 1,
288 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
289 | IEEE80211_HT_CAP_GRN_FLD
290 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_LSIG_TXOP_PROT,
291 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
292 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
293 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
294 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
295 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
296};
297
298static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
299 .channels = hdd_channels_5_ghz,
300 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
301 .band = IEEE80211_BAND_5GHZ,
302 .bitrates = a_mode_rates,
303 .n_bitrates = a_mode_rates_size,
304 .ht_cap.ht_supported = 1,
305 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
306 | IEEE80211_HT_CAP_GRN_FLD
307 | IEEE80211_HT_CAP_DSSSCCK40
308 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
309 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
310 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
311 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
312 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
313 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
314 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
315 .vht_cap.vht_supported = 1,
316};
317
318/* This structure contain information what kind of frame are expected in
319 TX/RX direction for each kind of interface */
320static const struct ieee80211_txrx_stypes
321 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
322 [NL80211_IFTYPE_STATION] = {
323 .tx = 0xffff,
324 .rx = BIT(SIR_MAC_MGMT_ACTION) |
325 BIT(SIR_MAC_MGMT_PROBE_REQ),
326 },
327 [NL80211_IFTYPE_AP] = {
328 .tx = 0xffff,
329 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_PROBE_REQ) |
332 BIT(SIR_MAC_MGMT_DISASSOC) |
333 BIT(SIR_MAC_MGMT_AUTH) |
334 BIT(SIR_MAC_MGMT_DEAUTH) |
335 BIT(SIR_MAC_MGMT_ACTION),
336 },
337 [NL80211_IFTYPE_ADHOC] = {
338 .tx = 0xffff,
339 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
340 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
341 BIT(SIR_MAC_MGMT_PROBE_REQ) |
342 BIT(SIR_MAC_MGMT_DISASSOC) |
343 BIT(SIR_MAC_MGMT_AUTH) |
344 BIT(SIR_MAC_MGMT_DEAUTH) |
345 BIT(SIR_MAC_MGMT_ACTION),
346 },
347 [NL80211_IFTYPE_P2P_CLIENT] = {
348 .tx = 0xffff,
349 .rx = BIT(SIR_MAC_MGMT_ACTION) |
350 BIT(SIR_MAC_MGMT_PROBE_REQ),
351 },
352 [NL80211_IFTYPE_P2P_GO] = {
353 /* This is also same as for SoftAP */
354 .tx = 0xffff,
355 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
357 BIT(SIR_MAC_MGMT_PROBE_REQ) |
358 BIT(SIR_MAC_MGMT_DISASSOC) |
359 BIT(SIR_MAC_MGMT_AUTH) |
360 BIT(SIR_MAC_MGMT_DEAUTH) |
361 BIT(SIR_MAC_MGMT_ACTION),
362 },
363};
364
365#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
366/* Interface limits and combinations registered by the driver */
367
368/* STA ( + STA ) combination */
369static const struct ieee80211_iface_limit
370 wlan_hdd_sta_iface_limit[] = {
371 {
372 .max = 3, /* p2p0 is a STA as well */
373 .types = BIT(NL80211_IFTYPE_STATION),
374 },
375};
376
377/* ADHOC (IBSS) limit */
378static const struct ieee80211_iface_limit
379 wlan_hdd_adhoc_iface_limit[] = {
380 {
381 .max = 1,
382 .types = BIT(NL80211_IFTYPE_STATION),
383 },
384 {
385 .max = 1,
386 .types = BIT(NL80211_IFTYPE_ADHOC),
387 },
388};
389
390/* AP ( + AP ) combination */
391static const struct ieee80211_iface_limit
392 wlan_hdd_ap_iface_limit[] = {
393 {
394 .max = (CDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
395 .types = BIT(NL80211_IFTYPE_AP),
396 },
397};
398
399/* P2P limit */
400static const struct ieee80211_iface_limit
401 wlan_hdd_p2p_iface_limit[] = {
402 {
403 .max = 1,
404 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
405 },
406 {
407 .max = 1,
408 .types = BIT(NL80211_IFTYPE_P2P_GO),
409 },
410};
411
412static const struct ieee80211_iface_limit
413 wlan_hdd_sta_ap_iface_limit[] = {
414 {
415 /* We need 1 extra STA interface for OBSS scan when SAP starts
416 * with HT40 in STA+SAP concurrency mode
417 */
418 .max = (1 + SAP_MAX_OBSS_STA_CNT),
419 .types = BIT(NL80211_IFTYPE_STATION),
420 },
421 {
422 .max = CDF_MAX_NO_OF_SAP_MODE,
423 .types = BIT(NL80211_IFTYPE_AP),
424 },
425};
426
427/* STA + P2P combination */
428static const struct ieee80211_iface_limit
429 wlan_hdd_sta_p2p_iface_limit[] = {
430 {
431 /* One reserved for dedicated P2PDEV usage */
432 .max = 2,
433 .types = BIT(NL80211_IFTYPE_STATION)
434 },
435 {
436 /* Support for two identical (GO + GO or CLI + CLI)
437 * or dissimilar (GO + CLI) P2P interfaces
438 */
439 .max = 2,
440 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
441 },
442};
443
444/* STA + AP + P2PGO combination */
445static const struct ieee80211_iface_limit
446wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
447 /* Support for AP+P2PGO interfaces */
448 {
449 .max = 2,
450 .types = BIT(NL80211_IFTYPE_STATION)
451 },
452 {
453 .max = 1,
454 .types = BIT(NL80211_IFTYPE_P2P_GO)
455 },
456 {
457 .max = 1,
458 .types = BIT(NL80211_IFTYPE_AP)
459 }
460};
461
462/* SAP + P2P combination */
463static const struct ieee80211_iface_limit
464wlan_hdd_sap_p2p_iface_limit[] = {
465 {
466 /* 1 dedicated for p2p0 which is a STA type */
467 .max = 1,
468 .types = BIT(NL80211_IFTYPE_STATION)
469 },
470 {
471 /* The p2p interface in SAP+P2P can be GO/CLI.
472 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
473 */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
476 },
477 {
478 /* SAP+GO to support only one SAP interface */
479 .max = 1,
480 .types = BIT(NL80211_IFTYPE_AP)
481 }
482};
483
484/* P2P + P2P combination */
485static const struct ieee80211_iface_limit
486wlan_hdd_p2p_p2p_iface_limit[] = {
487 {
488 /* 1 dedicated for p2p0 which is a STA type */
489 .max = 1,
490 .types = BIT(NL80211_IFTYPE_STATION)
491 },
492 {
493 /* The p2p interface in P2P+P2P can be GO/CLI.
494 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
495 */
496 .max = 2,
497 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
498 },
499};
500
501static struct ieee80211_iface_combination
502 wlan_hdd_iface_combination[] = {
503 /* STA */
504 {
505 .limits = wlan_hdd_sta_iface_limit,
506 .num_different_channels = 2,
507 .max_interfaces = 3,
508 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
509 },
510 /* ADHOC */
511 {
512 .limits = wlan_hdd_adhoc_iface_limit,
513 .num_different_channels = 1,
514 .max_interfaces = 2,
515 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
516 },
517 /* AP */
518 {
519 .limits = wlan_hdd_ap_iface_limit,
520 .num_different_channels = 2,
521 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + CDF_MAX_NO_OF_SAP_MODE),
522 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
523 },
524 /* P2P */
525 {
526 .limits = wlan_hdd_p2p_iface_limit,
527 .num_different_channels = 2,
528 .max_interfaces = 2,
529 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
530 },
531 /* STA + AP */
532 {
533 .limits = wlan_hdd_sta_ap_iface_limit,
534 .num_different_channels = 2,
535 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + CDF_MAX_NO_OF_SAP_MODE),
536 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
537 .beacon_int_infra_match = true,
538 },
539 /* STA + P2P */
540 {
541 .limits = wlan_hdd_sta_p2p_iface_limit,
542 .num_different_channels = 2,
543 /* one interface reserved for P2PDEV dedicated usage */
544 .max_interfaces = 4,
545 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
546 .beacon_int_infra_match = true,
547 },
548 /* STA + P2P GO + SAP */
549 {
550 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
551 /* we can allow 3 channels for three different persona
552 * but due to firmware limitation, allow max 2 concrnt channels.
553 */
554 .num_different_channels = 2,
555 /* one interface reserved for P2PDEV dedicated usage */
556 .max_interfaces = 4,
557 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
558 .beacon_int_infra_match = true,
559 },
560 /* SAP + P2P */
561 {
562 .limits = wlan_hdd_sap_p2p_iface_limit,
563 .num_different_channels = 2,
564 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
565 .max_interfaces = 3,
566 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
567 .beacon_int_infra_match = true,
568 },
569 /* P2P + P2P */
570 {
571 .limits = wlan_hdd_p2p_p2p_iface_limit,
572 .num_different_channels = 2,
573 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
574 .max_interfaces = 3,
575 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
576 .beacon_int_infra_match = true,
577 },
578};
579#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
580
581static struct cfg80211_ops wlan_hdd_cfg80211_ops;
582
583
584#ifdef WLAN_NL80211_TESTMODE
585enum wlan_hdd_tm_attr {
586 WLAN_HDD_TM_ATTR_INVALID = 0,
587 WLAN_HDD_TM_ATTR_CMD = 1,
588 WLAN_HDD_TM_ATTR_DATA = 2,
589 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
590 WLAN_HDD_TM_ATTR_TYPE = 4,
591 /* keep last */
592 WLAN_HDD_TM_ATTR_AFTER_LAST,
593 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
594};
595
596enum wlan_hdd_tm_cmd {
597 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
598 WLAN_HDD_TM_CMD_WLAN_HB = 1,
599};
600
601#define WLAN_HDD_TM_DATA_MAX_LEN 5000
602
603static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
604 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
605 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
606 .len = WLAN_HDD_TM_DATA_MAX_LEN},
607};
608#endif /* WLAN_NL80211_TESTMODE */
609
610#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
611static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
612 .flags = WIPHY_WOWLAN_MAGIC_PKT,
613 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
614 .pattern_min_len = 1,
615 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
616};
617#endif
618
619#ifdef FEATURE_WLAN_TDLS
620
621/* TDLS capabilities params */
622#define PARAM_MAX_TDLS_SESSION \
623 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
624#define PARAM_TDLS_FEATURE_SUPPORT \
625 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
626
627/**
628 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
629 * @wiphy: WIPHY structure pointer
630 * @wdev: Wireless device structure pointer
631 * @data: Pointer to the data received
632 * @data_len: Length of the data received
633 *
634 * This function provides TDLS capabilities
635 *
636 * Return: 0 on success and errno on failure
637 */
638static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
639 struct wireless_dev *wdev,
640 const void *data,
641 int data_len)
642{
643 int status;
644 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
645 struct sk_buff *skb;
646 uint32_t set = 0;
647
648 if (CDF_FTM_MODE == hdd_get_conparam()) {
649 hdd_err("Command not allowed in FTM mode");
650 return -EPERM;
651 }
652
653 status = wlan_hdd_validate_context(hdd_ctx);
654 if (status)
655 return status;
656
657 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
658 NLMSG_HDRLEN);
659 if (!skb) {
660 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
661 goto fail;
662 }
663
664 if (false == hdd_ctx->config->fEnableTDLSSupport) {
665 hddLog(LOGE,
666 FL("TDLS feature not Enabled or Not supported in FW"));
667 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
668 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
669 hddLog(LOGE, FL("nla put fail"));
670 goto fail;
671 }
672 } else {
673 set = set | WIFI_TDLS_SUPPORT;
674 set = set | (hdd_ctx->config->fTDLSExternalControl ?
675 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
676 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
677 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
678 hddLog(LOG1, FL("TDLS Feature supported value %x"), set);
679 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
680 hdd_ctx->max_num_tdls_sta) ||
681 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
682 set)) {
683 hddLog(LOGE, FL("nla put fail"));
684 goto fail;
685 }
686 }
687 return cfg80211_vendor_cmd_reply(skb);
688fail:
689 if (skb)
690 kfree_skb(skb);
691 return -EINVAL;
692}
693
694/**
695 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
696 * @wiphy: WIPHY structure pointer
697 * @wdev: Wireless device structure pointer
698 * @data: Pointer to the data received
699 * @data_len: Length of the data received
700 *
701 * This function provides TDLS capabilities
702 *
703 * Return: 0 on success and errno on failure
704 */
705static int
706wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
707 struct wireless_dev *wdev,
708 const void *data,
709 int data_len)
710{
711 int ret;
712
713 cds_ssr_protect(__func__);
714 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
715 data, data_len);
716 cds_ssr_unprotect(__func__);
717
718 return ret;
719}
720#endif
721
722#ifdef QCA_HT_2040_COEX
723static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
724#endif
725
726#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
727/*
728 * FUNCTION: wlan_hdd_send_avoid_freq_event
729 * This is called when wlan driver needs to send vendor specific
730 * avoid frequency range event to userspace
731 */
732int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
733 tHddAvoidFreqList *pAvoidFreqList)
734{
735 struct sk_buff *vendor_event;
736
737 ENTER();
738
739 if (!pHddCtx) {
740 hddLog(LOGE, FL("HDD context is null"));
741 return -EINVAL;
742 }
743
744 if (!pAvoidFreqList) {
745 hddLog(LOGE, FL("pAvoidFreqList is null"));
746 return -EINVAL;
747 }
748
749 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
750 NULL,
751 sizeof(tHddAvoidFreqList),
752 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
753 GFP_KERNEL);
754 if (!vendor_event) {
755 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
756 return -EINVAL;
757 }
758
759 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
760 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
761
762 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
763
764 EXIT();
765 return 0;
766}
767#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
768
769/* vendor specific events */
770static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
771#ifdef FEATURE_WLAN_CH_AVOID
772 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
773 .vendor_id =
774 QCA_NL80211_VENDOR_ID,
775 .subcmd =
776 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
777 },
778#endif /* FEATURE_WLAN_CH_AVOID */
779
780#ifdef WLAN_FEATURE_NAN
781 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
782 .vendor_id =
783 QCA_NL80211_VENDOR_ID,
784 .subcmd =
785 QCA_NL80211_VENDOR_SUBCMD_NAN
786 },
787#endif
788
789#ifdef WLAN_FEATURE_STATS_EXT
790 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
791 .vendor_id =
792 QCA_NL80211_VENDOR_ID,
793 .subcmd =
794 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
795 },
796#endif /* WLAN_FEATURE_STATS_EXT */
797#ifdef FEATURE_WLAN_EXTSCAN
798 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
799 .vendor_id =
800 QCA_NL80211_VENDOR_ID,
801 .subcmd =
802 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
803 },
804 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
805 .vendor_id =
806 QCA_NL80211_VENDOR_ID,
807 .subcmd =
808 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
809 },
810 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
811 .
812 vendor_id
813 =
814 QCA_NL80211_VENDOR_ID,
815 .subcmd =
816 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
817 },
818 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
819 .
820 vendor_id
821 =
822 QCA_NL80211_VENDOR_ID,
823 .
824 subcmd =
825 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
826 },
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
828 .
829 vendor_id
830 =
831 QCA_NL80211_VENDOR_ID,
832 .
833 subcmd
834 =
835 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
836 },
837 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
838 .
839 vendor_id
840 =
841 QCA_NL80211_VENDOR_ID,
842 .subcmd =
843 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
844 },
845 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
846 .vendor_id =
847 QCA_NL80211_VENDOR_ID,
848 .subcmd =
849 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
850 },
851 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
852 .
853 vendor_id
854 =
855 QCA_NL80211_VENDOR_ID,
856 .subcmd =
857 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
858 },
859 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
860 .
861 vendor_id
862 =
863 QCA_NL80211_VENDOR_ID,
864 .subcmd =
865 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
866 },
867 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
868 .
869 vendor_id
870 =
871 QCA_NL80211_VENDOR_ID,
872 .
873 subcmd
874 =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
878 .
879 vendor_id
880 =
881 QCA_NL80211_VENDOR_ID,
882 .
883 subcmd =
884 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
885 },
886 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
887 .
888 vendor_id
889 =
890 QCA_NL80211_VENDOR_ID,
891 .
892 subcmd
893 =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
907 .vendor_id = QCA_NL80211_VENDOR_ID,
908 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
909 },
910 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
911 .vendor_id = QCA_NL80211_VENDOR_ID,
912 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
913 },
914#endif /* FEATURE_WLAN_EXTSCAN */
915
916#ifdef WLAN_FEATURE_LINK_LAYER_STATS
917 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
918 .vendor_id =
919 QCA_NL80211_VENDOR_ID,
920 .subcmd =
921 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
922 },
923 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
924 .vendor_id =
925 QCA_NL80211_VENDOR_ID,
926 .subcmd =
927 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
928 },
929 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
930 .vendor_id =
931 QCA_NL80211_VENDOR_ID,
932 .subcmd =
933 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
936 .vendor_id =
937 QCA_NL80211_VENDOR_ID,
938 .subcmd =
939 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
940 },
941 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
942 .vendor_id =
943 QCA_NL80211_VENDOR_ID,
944 .subcmd =
945 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
946 },
947 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
948 .vendor_id =
949 QCA_NL80211_VENDOR_ID,
950 .subcmd =
951 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
952 },
953#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
954 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
955 .vendor_id =
956 QCA_NL80211_VENDOR_ID,
957 .subcmd =
958 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
959 },
960 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
961 .vendor_id = QCA_NL80211_VENDOR_ID,
962 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
963 },
964#ifdef WLAN_FEATURE_ROAM_OFFLOAD
965 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
966 .vendor_id =
967 QCA_NL80211_VENDOR_ID,
968 .subcmd =
969 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
970 },
971#endif
972 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
973 .vendor_id =
974 QCA_NL80211_VENDOR_ID,
975 .subcmd =
976 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
977 },
978 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
979 .vendor_id =
980 QCA_NL80211_VENDOR_ID,
981 .subcmd =
982 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
983 },
984 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
985 .vendor_id =
986 QCA_NL80211_VENDOR_ID,
987 .subcmd =
988 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
989 },
990 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
995 },
996 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
997 .vendor_id =
998 QCA_NL80211_VENDOR_ID,
999 .subcmd =
1000 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1001 },
1002#ifdef FEATURE_WLAN_EXTSCAN
1003 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1004 .vendor_id = QCA_NL80211_VENDOR_ID,
1005 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1008 .vendor_id = QCA_NL80211_VENDOR_ID,
1009 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1010 },
1011 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1012 .vendor_id = QCA_NL80211_VENDOR_ID,
1013 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1014 },
1015 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1016 .vendor_id = QCA_NL80211_VENDOR_ID,
1017 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1020 .vendor_id = QCA_NL80211_VENDOR_ID,
1021 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1022 },
1023#endif /* FEATURE_WLAN_EXTSCAN */
1024 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1025 .vendor_id = QCA_NL80211_VENDOR_ID,
1026 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1027 },
1028#ifdef WLAN_FEATURE_MEMDUMP
1029 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1030 .vendor_id = QCA_NL80211_VENDOR_ID,
1031 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1032 },
1033#endif /* WLAN_FEATURE_MEMDUMP */
1034 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1035 .vendor_id = QCA_NL80211_VENDOR_ID,
1036 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1037 },
1038 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1041 },
1042 /* OCB events */
1043 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1046 },
1047};
1048
1049/**
1050 * __is_driver_dfs_capable() - get driver DFS capability
1051 * @wiphy: pointer to wireless wiphy structure.
1052 * @wdev: pointer to wireless_dev structure.
1053 * @data: Pointer to the data to be passed via vendor interface
1054 * @data_len:Length of the data to be passed
1055 *
1056 * This function is called by userspace to indicate whether or not
1057 * the driver supports DFS offload.
1058 *
1059 * Return: 0 on success, negative errno on failure
1060 */
1061static int __is_driver_dfs_capable(struct wiphy *wiphy,
1062 struct wireless_dev *wdev,
1063 const void *data,
1064 int data_len)
1065{
1066 u32 dfs_capability = 0;
1067 struct sk_buff *temp_skbuff;
1068 int ret_val;
1069 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1070
1071 ENTER();
1072
1073 ret_val = wlan_hdd_validate_context(hdd_ctx);
1074 if (ret_val)
1075 return ret_val;
1076
1077 if (CDF_FTM_MODE == hdd_get_conparam()) {
1078 hdd_err("Command not allowed in FTM mode");
1079 return -EPERM;
1080 }
1081
1082#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0))
1083 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
1084#endif
1085
1086 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1087 NLMSG_HDRLEN);
1088
1089 if (temp_skbuff != NULL) {
1090 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1091 dfs_capability);
1092 if (ret_val) {
1093 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail"));
1094 kfree_skb(temp_skbuff);
1095
1096 return ret_val;
1097 }
1098
1099 return cfg80211_vendor_cmd_reply(temp_skbuff);
1100 }
1101
1102 hddLog(LOGE, FL("dfs capability: buffer alloc fail"));
1103 return -ENOMEM;
1104}
1105
1106/**
1107 * is_driver_dfs_capable() - get driver DFS capability
1108 * @wiphy: pointer to wireless wiphy structure.
1109 * @wdev: pointer to wireless_dev structure.
1110 * @data: Pointer to the data to be passed via vendor interface
1111 * @data_len:Length of the data to be passed
1112 *
1113 * This function is called by userspace to indicate whether or not
1114 * the driver supports DFS offload. This is an SSR-protected
1115 * wrapper function.
1116 *
1117 * Return: 0 on success, negative errno on failure
1118 */
1119static int is_driver_dfs_capable(struct wiphy *wiphy,
1120 struct wireless_dev *wdev,
1121 const void *data,
1122 int data_len)
1123{
1124 int ret;
1125
1126 cds_ssr_protect(__func__);
1127 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1128 cds_ssr_unprotect(__func__);
1129
1130 return ret;
1131}
1132
1133/**
1134 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1135 *
1136 * @adapter: SAP adapter pointer
1137 *
1138 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1139 * radio. So in case of DFS MCC scenario override current SAP given config
1140 * to follow concurrent SAP DFS config
1141 *
1142 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1143 */
1144
1145#ifdef WLAN_FEATURE_MBSSID
1146int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1147{
1148 hdd_adapter_t *con_sap_adapter;
1149 tsap_Config_t *sap_config, *con_sap_config;
1150 int con_ch;
1151
1152 /*
1153 * Check if AP+AP case, once primary AP chooses a DFS
1154 * channel secondary AP should always follow primary APs channel
1155 */
1156 if (!cds_concurrent_beaconing_sessions_running())
1157 return 0;
1158
1159 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1160 if (!con_sap_adapter)
1161 return 0;
1162
1163 sap_config = &adapter->sessionCtx.ap.sapConfig;
1164 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1165 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1166
1167 if (!CDS_IS_DFS_CH(con_ch))
1168 return 0;
1169
1170 hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"),
1171 sap_config->channel, con_ch);
1172 hddLog(LOG1, FL("Overriding guest AP's channel"));
1173 sap_config->channel = con_ch;
1174
1175 if (con_sap_config->acs_cfg.acs_mode == true) {
1176 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1177 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
1178 hddLog(LOGE, FL("Primary AP channel config error"));
1179 hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"),
1180 con_ch, con_sap_config->acs_cfg.pri_ch,
1181 con_sap_config->acs_cfg.ht_sec_ch);
1182 return -EINVAL;
1183 }
1184 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1185 * MCC restriction. So free ch list allocated in do_acs
1186 * func for Sec AP and realloc for Pri AP ch list size
1187 */
1188 if (sap_config->acs_cfg.ch_list)
1189 cdf_mem_free(sap_config->acs_cfg.ch_list);
1190
1191 cdf_mem_copy(&sap_config->acs_cfg,
1192 &con_sap_config->acs_cfg,
1193 sizeof(struct sap_acs_cfg));
1194 sap_config->acs_cfg.ch_list = cdf_mem_malloc(
1195 sizeof(uint8_t) *
1196 con_sap_config->acs_cfg.ch_list_count);
1197 if (!sap_config->acs_cfg.ch_list) {
1198 hddLog(LOGE, FL("ACS config alloc fail"));
1199 return -ENOMEM;
1200 }
1201
1202 cdf_mem_copy(sap_config->acs_cfg.ch_list,
1203 con_sap_config->acs_cfg.ch_list,
1204 con_sap_config->acs_cfg.ch_list_count);
1205
1206 } else {
1207 sap_config->acs_cfg.pri_ch = con_ch;
1208 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1209 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1210 }
1211
1212 return con_ch;
1213}
1214#else
1215int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1216{
1217 return 0;
1218}
1219#endif
1220
1221/**
1222 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1223 * @sap_cfg: pointer to SAP config struct
1224 *
1225 * This function sets the default ACS start and end channel for the given band
1226 * and also parses the given ACS channel list.
1227 *
1228 * Return: None
1229 */
1230
1231static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1232 bool vht_enabled)
1233{
1234 int i;
1235 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1236 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
1237 sap_cfg->acs_cfg.start_ch = rf_channels[RF_CHAN_1].channelNum;
1238 sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_14].channelNum;
1239 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1240 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
1241 sap_cfg->acs_cfg.start_ch = rf_channels[RF_CHAN_1].channelNum;
1242 sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_13].channelNum;
1243 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1244 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
1245 sap_cfg->acs_cfg.start_ch = rf_channels[RF_CHAN_36].channelNum;
1246 sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_165].channelNum;
1247 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1248 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
1249 sap_cfg->acs_cfg.start_ch = rf_channels[RF_CHAN_1].channelNum;
1250 sap_cfg->acs_cfg.end_ch = rf_channels[RF_CHAN_165].channelNum;
1251 }
1252
1253 if (ht_enabled)
1254 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1255
1256 if (vht_enabled)
1257 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1258
1259
1260 /* Parse ACS Chan list from hostapd */
1261 if (!sap_cfg->acs_cfg.ch_list)
1262 return;
1263
1264 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1265 sap_cfg->acs_cfg.end_ch =
1266 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1267 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
1268 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i])
1269 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1270 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1271 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1272 }
1273}
1274
1275
1276static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1277
1278/**
1279 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1280 * @adapter: pointer to SAP adapter struct
1281 *
1282 * This function starts the ACS procedure if there are no
1283 * constraints like MBSSID DFS restrictions.
1284 *
1285 * Return: Status of ACS Start procedure
1286 */
1287
1288static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1289{
1290
1291 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1292 tsap_Config_t *sap_config;
1293 tpWLAN_SAPEventCB acs_event_callback;
1294 int status;
1295
1296 sap_config = &adapter->sessionCtx.ap.sapConfig;
1297 sap_config->channel = AUTO_CHANNEL_SELECT;
1298
1299 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1300 if (status < 0) {
1301 return status;
1302 } else {
1303 if (status > 0) {
1304 /*notify hostapd about channel override */
1305 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1306 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1307 return 0;
1308 }
1309 }
1310 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1311 if (status) {
1312 hddLog(LOGE, FL("ACS config failed"));
1313 return -EINVAL;
1314 }
1315
1316 acs_event_callback = hdd_hostapd_sap_event_cb;
1317
1318 cdf_mem_copy(sap_config->self_macaddr.bytes,
1319 adapter->macAddressCurrent.bytes, sizeof(struct cdf_mac_addr));
1320 hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex);
1321 status = wlansap_acs_chselect(
1322#ifdef WLAN_FEATURE_MBSSID
1323 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1324#else
1325 hdd_ctx->pcds_context,
1326#endif
1327 acs_event_callback, sap_config, adapter->dev);
1328
1329
1330 if (status) {
1331 hddLog(LOGE, FL("ACS channel select failed"));
1332 return -EINVAL;
1333 }
1334 sap_config->acs_cfg.acs_mode = true;
1335 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1336
1337 return 0;
1338}
1339
1340/**
1341 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1342 * @wiphy: Linux wiphy struct pointer
1343 * @wdev: Linux wireless device struct pointer
1344 * @data: ACS information from hostapd
1345 * @data_len: ACS information length
1346 *
1347 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1348 * and starts ACS procedure.
1349 *
1350 * Return: ACS procedure start status
1351 */
1352
1353static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1354 struct wireless_dev *wdev,
1355 const void *data, int data_len)
1356{
1357 struct net_device *ndev = wdev->netdev;
1358 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1359 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1360 tsap_Config_t *sap_config;
1361 struct sk_buff *temp_skbuff;
1362 int status = -EINVAL, i = 0;
1363 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1364 bool ht_enabled, ht40_enabled, vht_enabled;
1365 uint8_t ch_width;
1366
1367 /* ***Note*** Donot set SME config related to ACS operation here because
1368 * ACS operation is not synchronouse and ACS for Second AP may come when
1369 * ACS operation for first AP is going on. So only do_acs is split to
1370 * seperate start_acs routine. Also SME-PMAC struct that is used to
1371 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1372 * config shall be set only from start_acs.
1373 */
1374
1375 /* nla_policy Policy template. Policy not applied as some attributes are
1376 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1377 *
1378 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1379 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1380 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1381 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1382 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1383 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1384 */
1385
1386 if (CDF_FTM_MODE == hdd_get_conparam()) {
1387 hdd_err("Command not allowed in FTM mode");
1388 return -EPERM;
1389 }
1390
1391 if (hdd_ctx->config->force_sap_acs) {
1392 hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled"));
1393 return -EPERM;
1394 }
1395
1396 status = wlan_hdd_validate_context(hdd_ctx);
1397 if (0 != status) {
1398 hddLog(LOGE, FL("HDD context is not valid"));
1399 goto out;
1400 }
1401 sap_config = &adapter->sessionCtx.ap.sapConfig;
1402 cdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
1403
1404 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1405 NULL);
1406 if (status) {
1407 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
1408 goto out;
1409 }
1410
1411 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
1412 hddLog(CDF_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed"));
1413 goto out;
1414 }
1415 sap_config->acs_cfg.hw_mode = nla_get_u8(
1416 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1417
1418 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1419 ht_enabled =
1420 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1421 else
1422 ht_enabled = 0;
1423
1424 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1425 ht40_enabled =
1426 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1427 else
1428 ht40_enabled = 0;
1429
1430 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1431 vht_enabled =
1432 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1433 else
1434 vht_enabled = 0;
1435
1436 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1437 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1438 } else {
1439 if (ht_enabled && ht40_enabled)
1440 ch_width = 40;
1441 else
1442 ch_width = 20;
1443 }
1444 if (ch_width == 80)
1445 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1446 else if (ch_width == 40)
1447 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1448 else
1449 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1450
1451 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1452 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1453 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1454 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1455 * since it contains the frequency values of the channels in
1456 * the channel list.
1457 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1458 * is present
1459 */
1460 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1461 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1462 sap_config->acs_cfg.ch_list_count = nla_len(
1463 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1464 if (sap_config->acs_cfg.ch_list_count) {
1465 sap_config->acs_cfg.ch_list = cdf_mem_malloc(
1466 sizeof(uint8_t) *
1467 sap_config->acs_cfg.ch_list_count);
1468 if (sap_config->acs_cfg.ch_list == NULL)
1469 goto out;
1470
1471 cdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
1472 sap_config->acs_cfg.ch_list_count);
1473 }
1474 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1475 uint32_t *freq =
1476 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1477 sap_config->acs_cfg.ch_list_count = nla_len(
1478 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1479 sizeof(uint32_t);
1480 if (sap_config->acs_cfg.ch_list_count) {
1481 sap_config->acs_cfg.ch_list = cdf_mem_malloc(
1482 sap_config->acs_cfg.ch_list_count);
1483 if (sap_config->acs_cfg.ch_list == NULL) {
1484 hddLog(LOGE, FL("ACS config alloc fail"));
1485 status = -ENOMEM;
1486 goto out;
1487 }
1488
1489 /* convert frequency to channel */
1490 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1491 sap_config->acs_cfg.ch_list[i] =
1492 ieee80211_frequency_to_channel(freq[i]);
1493 }
1494 }
1495
1496 hdd_debug("get pcl for DO_ACS vendor command");
1497
1498 /* consult policy manager to get PCL */
1499 status = cds_get_pcl(hdd_ctx, CDS_SAP_MODE,
1500 sap_config->acs_cfg.pcl_channels,
1501 &sap_config->acs_cfg.pcl_ch_count);
1502 if (CDF_STATUS_SUCCESS != status)
1503 hddLog(LOGE, FL("Get PCL failed"));
1504
1505 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1506
1507 /* ACS override for android */
1508 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
1509 hddLog(LOG1, FL("ACS Config override for 11AC"));
1510 vht_enabled = 1;
1511 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1512 sap_config->acs_cfg.ch_width =
1513 hdd_ctx->config->vhtChannelWidth;
1514 /* No VHT80 in 2.4G so perform ACS accordingly */
1515 if (sap_config->acs_cfg.end_ch <= 14 &&
1516 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1517 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1518 }
1519
1520 hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"),
1521 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1522 ch_width, ht_enabled, vht_enabled,
1523 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1524
1525 if (sap_config->acs_cfg.ch_list_count) {
1526 hddLog(LOG1, FL("ACS channel list: len: %d"),
1527 sap_config->acs_cfg.ch_list_count);
1528 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1529 hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]);
1530 }
1531 sap_config->acs_cfg.acs_mode = true;
1532 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
1533 /* ***Note*** Completion variable usage is not allowed here since
1534 * ACS scan operation may take max 2.2 sec for 5G band.
1535 * 9 Active channel X 40 ms active scan time +
1536 * 16 Passive channel X 110ms passive scan time
1537 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1538 * for this long. So we split up the scanning part.
1539 */
1540 set_bit(ACS_PENDING, &adapter->event_flags);
1541 hddLog(LOG1, FL("ACS Pending for wlan%d"),
1542 adapter->dev->ifindex);
1543 status = 0;
1544 } else {
1545 status = wlan_hdd_cfg80211_start_acs(adapter);
1546 }
1547
1548out:
1549 if (0 == status) {
1550 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1551 NLMSG_HDRLEN);
1552 if (temp_skbuff != NULL)
1553 return cfg80211_vendor_cmd_reply(temp_skbuff);
1554 }
1555
1556 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1557
1558 return status;
1559}
1560
1561 /**
1562 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1563 * @wiphy: Linux wiphy struct pointer
1564 * @wdev: Linux wireless device struct pointer
1565 * @data: ACS information from hostapd
1566 * @data_len: ACS information len
1567 *
1568 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1569 * and starts ACS procedure.
1570 *
1571 * Return: ACS procedure start status
1572 */
1573
1574static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1575 struct wireless_dev *wdev,
1576 const void *data, int data_len)
1577{
1578 int ret;
1579
1580 cds_ssr_protect(__func__);
1581 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1582 cds_ssr_unprotect(__func__);
1583
1584 return ret;
1585}
1586
1587/**
1588 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1589 * @work: Linux workqueue struct pointer for ACS work
1590 *
1591 * This function starts the ACS procedure which was marked pending when an ACS
1592 * procedure was in progress for a concurrent SAP interface.
1593 *
1594 * Return: None
1595 */
1596
1597static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1598{
1599 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1600 acs_pending_work.work);
1601 wlan_hdd_cfg80211_start_acs(adapter);
1602}
1603
1604/**
1605 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1606 * @adapter: Pointer to SAP adapter struct
1607 * @pri_channel: SAP ACS procedure selected Primary channel
1608 * @sec_channel: SAP ACS procedure selected secondary channel
1609 *
1610 * This is a callback function from SAP module on ACS procedure is completed.
1611 * This function send the ACS selected channel information to hostapd
1612 *
1613 * Return: None
1614 */
1615
1616void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1617{
1618 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1619 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1620 struct sk_buff *vendor_event;
1621 int ret_val;
1622 hdd_adapter_t *con_sap_adapter;
1623 uint16_t ch_width;
1624
1625 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1626 NULL,
1627 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1628 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1629 GFP_KERNEL);
1630
1631 if (!vendor_event) {
1632 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
1633 return;
1634 }
1635
1636 ret_val = hdd_vendor_put_ifindex(vendor_event, adapter->dev->ifindex);
1637 if (ret_val) {
1638 hddLog(LOGE, FL("NL80211_ATTR_IFINDEX put fail"));
1639 kfree_skb(vendor_event);
1640 return;
1641 }
1642
1643 ret_val = nla_put_u8(vendor_event,
1644 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1645 sap_cfg->acs_cfg.pri_ch);
1646 if (ret_val) {
1647 hddLog(LOGE,
1648 FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail"));
1649 kfree_skb(vendor_event);
1650 return;
1651 }
1652
1653 ret_val = nla_put_u8(vendor_event,
1654 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1655 sap_cfg->acs_cfg.ht_sec_ch);
1656 if (ret_val) {
1657 hddLog(LOGE,
1658 FL(
1659 "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail"));
1660 kfree_skb(vendor_event);
1661 return;
1662 }
1663
1664 ret_val = nla_put_u8(vendor_event,
1665 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1666 sap_cfg->acs_cfg.vht_seg0_center_ch);
1667 if (ret_val) {
1668 hddLog(LOGE,
1669 FL(
1670 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail"));
1671 kfree_skb(vendor_event);
1672 return;
1673 }
1674
1675 ret_val = nla_put_u8(vendor_event,
1676 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1677 sap_cfg->acs_cfg.vht_seg1_center_ch);
1678 if (ret_val) {
1679 hddLog(LOGE,
1680 FL(
1681 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail"));
1682 kfree_skb(vendor_event);
1683 return;
1684 }
1685
1686 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1687 ch_width = 80;
1688 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1689 ch_width = 40;
1690 else
1691 ch_width = 20;
1692
1693 ret_val = nla_put_u16(vendor_event,
1694 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1695 ch_width);
1696 if (ret_val) {
1697 hddLog(LOGE,
1698 FL(
1699 "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail"));
1700 kfree_skb(vendor_event);
1701 return;
1702 }
1703 if (sap_cfg->acs_cfg.pri_ch > 14)
1704 ret_val = nla_put_u8(vendor_event,
1705 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1706 QCA_ACS_MODE_IEEE80211A);
1707 else
1708 ret_val = nla_put_u8(vendor_event,
1709 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1710 QCA_ACS_MODE_IEEE80211G);
1711
1712 if (ret_val) {
1713 hddLog(LOGE,
1714 FL(
1715 "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail"));
1716 kfree_skb(vendor_event);
1717 return;
1718 }
1719
1720 hddLog(LOG1,
1721 FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"),
1722 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1723 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1724 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1725
1726 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1727 /* ***Note*** As already mentioned Completion variable usage is not
1728 * allowed here since ACS scan operation may take max 2.2 sec.
1729 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1730 * operation.
1731 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1732 * when Primary AP ACS is complete and secondary AP ACS is started here
1733 * immediately, Primary AP start_bss may come inbetween ACS operation
1734 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1735 * delay. This path and below constraint will be removed on sessionizing
1736 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1737 * As per design constraint user space control application must take
1738 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1739 * this code path. Sec AP hostapd should be started after Primary AP
1740 * start beaconing which can be confirmed by getchannel iwpriv command
1741 */
1742
1743 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1744 if (con_sap_adapter &&
1745 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
1746#ifdef CONFIG_CNSS
1747 cnss_init_delayed_work(&con_sap_adapter->acs_pending_work,
1748 wlan_hdd_cfg80211_start_pending_acs);
1749#else
1750 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1751 wlan_hdd_cfg80211_start_pending_acs);
1752#endif
1753 /* Lets give 500ms for OBSS + START_BSS to complete */
1754 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1755 msecs_to_jiffies(500));
1756 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1757 }
1758
1759 return;
1760}
1761
1762static int
1763__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1764 struct wireless_dev *wdev,
1765 const void *data,
1766 int data_len)
1767{
1768 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1769 struct sk_buff *skb = NULL;
1770 uint32_t fset = 0;
1771 int ret;
1772
1773 if (CDF_FTM_MODE == hdd_get_conparam()) {
1774 hdd_err("Command not allowed in FTM mode");
1775 return -EPERM;
1776 }
1777
1778 ret = wlan_hdd_validate_context(pHddCtx);
1779 if (0 != ret) {
1780 hddLog(LOGE, FL("Hdd context not valid"));
1781 return -EINVAL;
1782 }
1783
1784 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
1785 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
1786 fset |= WIFI_FEATURE_INFRA;
1787 }
1788 if (true == hdd_is_5g_supported(pHddCtx)) {
1789 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
1790 fset |= WIFI_FEATURE_INFRA_5G;
1791 }
1792#ifdef WLAN_FEATURE_P2P
1793 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1794 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
1795 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
1796 fset |= WIFI_FEATURE_P2P;
1797 }
1798#endif
1799 fset |= WIFI_FEATURE_SOFT_AP;
1800
1801 /* HOTSPOT is a supplicant feature, enable it by default */
1802 fset |= WIFI_FEATURE_HOTSPOT;
1803
1804#ifdef FEATURE_WLAN_EXTSCAN
1805 if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
1806 hddLog(LOG1, FL("EXTScan is supported by firmware"));
1807 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1808 }
1809#endif
1810 if (wlan_hdd_nan_is_supported()) {
1811 hddLog(LOG1, FL("NAN is supported by firmware"));
1812 fset |= WIFI_FEATURE_NAN;
1813 }
1814 if (sme_is_feature_supported_by_fw(RTT)) {
1815 hddLog(LOG1, FL("RTT is supported by firmware"));
1816 fset |= WIFI_FEATURE_D2D_RTT;
1817 fset |= WIFI_FEATURE_D2AP_RTT;
1818 }
1819#ifdef FEATURE_WLAN_SCAN_PNO
1820 if (pHddCtx->config->configPNOScanSupport &&
1821 sme_is_feature_supported_by_fw(PNO)) {
1822 hddLog(LOG1, FL("PNO is supported by firmware"));
1823 fset |= WIFI_FEATURE_PNO;
1824 }
1825#endif
1826 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1827#ifdef FEATURE_WLAN_TDLS
1828 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1829 sme_is_feature_supported_by_fw(TDLS)) {
1830 hddLog(LOG1, FL("TDLS is supported by firmware"));
1831 fset |= WIFI_FEATURE_TDLS;
1832 }
1833 if (sme_is_feature_supported_by_fw(TDLS) &&
1834 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1835 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
1836 hddLog(LOG1, FL("TDLS off-channel is supported by firmware"));
1837 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1838 }
1839#endif
1840#ifdef WLAN_AP_STA_CONCURRENCY
1841 fset |= WIFI_FEATURE_AP_STA;
1842#endif
1843 fset |= WIFI_FEATURE_RSSI_MONITOR;
1844
1845 if (hdd_link_layer_stats_supported())
1846 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1847
1848 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1849 NLMSG_HDRLEN);
1850 if (!skb) {
1851 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1852 return -EINVAL;
1853 }
1854 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
1855 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
1856 hddLog(LOGE, FL("nla put fail"));
1857 goto nla_put_failure;
1858 }
1859 return cfg80211_vendor_cmd_reply(skb);
1860nla_put_failure:
1861 kfree_skb(skb);
1862 return -EINVAL;
1863}
1864
1865/**
1866 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1867 * @wiphy: pointer to wireless wiphy structure.
1868 * @wdev: pointer to wireless_dev structure.
1869 * @data: Pointer to the data to be passed via vendor interface
1870 * @data_len:Length of the data to be passed
1871 *
1872 * Return: Return the Success or Failure code.
1873 */
1874static int
1875wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1876 struct wireless_dev *wdev,
1877 const void *data, int data_len)
1878{
1879 int ret = 0;
1880
1881 cds_ssr_protect(__func__);
1882 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1883 data, data_len);
1884 cds_ssr_unprotect(__func__);
1885
1886 return ret;
1887}
1888
1889/**
1890 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1891 * @wiphy: pointer to wireless wiphy structure.
1892 * @wdev: pointer to wireless_dev structure.
1893 * @data: Pointer to the data to be passed via vendor interface
1894 * @data_len:Length of the data to be passed
1895 *
1896 * Set the MAC address that is to be used for scanning.
1897 *
1898 * Return: Return the Success or Failure code.
1899 */
1900static int
1901__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1902 struct wireless_dev *wdev,
1903 const void *data,
1904 int data_len)
1905{
1906 tpSirScanMacOui pReqMsg = NULL;
1907 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1908 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
1909 CDF_STATUS status;
1910 int ret;
1911
1912 ENTER();
1913
1914 if (CDF_FTM_MODE == hdd_get_conparam()) {
1915 hdd_err("Command not allowed in FTM mode");
1916 return -EPERM;
1917 }
1918
1919 ret = wlan_hdd_validate_context(pHddCtx);
1920 if (0 != ret) {
1921 hddLog(LOGE, FL("HDD context is not valid"));
1922 return ret;
1923 }
1924
1925 if (false == pHddCtx->config->enable_mac_spoofing) {
1926 hddLog(LOGW, FL("MAC address spoofing is not enabled"));
1927 return -ENOTSUPP;
1928 }
1929
1930 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1931 data, data_len, NULL)) {
1932 hddLog(LOGE, FL("Invalid ATTR"));
1933 return -EINVAL;
1934 }
1935 pReqMsg = cdf_mem_malloc(sizeof(*pReqMsg));
1936 if (!pReqMsg) {
1937 hddLog(LOGE, FL("cdf_mem_malloc failed"));
1938 return -ENOMEM;
1939 }
1940 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
1941 hddLog(LOGE, FL("attr mac oui failed"));
1942 goto fail;
1943 }
1944 nla_memcpy(&pReqMsg->oui[0],
1945 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1946 sizeof(pReqMsg->oui));
1947 hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0],
1948 pReqMsg->oui[1], pReqMsg->oui[2]);
1949 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
1950 if (!CDF_IS_STATUS_SUCCESS(status)) {
1951 hddLog(CDF_TRACE_LEVEL_ERROR,
1952 FL("sme_set_scanning_mac_oui failed(err=%d)"), status);
1953 goto fail;
1954 }
1955 return 0;
1956fail:
1957 cdf_mem_free(pReqMsg);
1958 return -EINVAL;
1959}
1960
1961/**
1962 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1963 * @wiphy: pointer to wireless wiphy structure.
1964 * @wdev: pointer to wireless_dev structure.
1965 * @data: Pointer to the data to be passed via vendor interface
1966 * @data_len:Length of the data to be passed
1967 *
1968 * Set the MAC address that is to be used for scanning. This is an
1969 * SSR-protecting wrapper function.
1970 *
1971 * Return: Return the Success or Failure code.
1972 */
1973static int
1974wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1975 struct wireless_dev *wdev,
1976 const void *data,
1977 int data_len)
1978{
1979 int ret;
1980
1981 cds_ssr_protect(__func__);
1982 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
1983 data, data_len);
1984 cds_ssr_unprotect(__func__);
1985
1986 return ret;
1987}
1988
1989/**
1990 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
1991 * @feature_flags: pointer to the byte array of features.
1992 * @feature: Feature to be turned ON in the byte array.
1993 *
1994 * Return: None
1995 *
1996 * This is called to turn ON or SET the feature flag for the requested feature.
1997 **/
1998#define NUM_BITS_IN_BYTE 8
1999void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2000{
2001 uint32_t index;
2002 uint8_t bit_mask;
2003
2004 index = feature / NUM_BITS_IN_BYTE;
2005 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2006 feature_flags[index] |= bit_mask;
2007}
2008
2009/**
2010 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2011 * @wiphy: pointer to wireless wiphy structure.
2012 * @wdev: pointer to wireless_dev structure.
2013 * @data: Pointer to the data to be passed via vendor interface
2014 * @data_len:Length of the data to be passed
2015 *
2016 * This is called when wlan driver needs to send supported feature set to
2017 * supplicant upon a request/query from the supplicant.
2018 *
2019 * Return: Return the Success or Failure code.
2020 **/
2021#define MAX_CONCURRENT_CHAN_ON_24G 2
2022#define MAX_CONCURRENT_CHAN_ON_5G 2
2023static int
2024__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2025 struct wireless_dev *wdev,
2026 const void *data, int data_len)
2027{
2028 struct sk_buff *skb = NULL;
2029 uint32_t dbs_capability = 0;
2030 bool one_by_one_dbs, two_by_two_dbs;
2031 CDF_STATUS ret = CDF_STATUS_E_FAILURE;
2032 int ret_val;
2033
2034 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2035 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2036
2037 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2038 if (ret_val)
2039 return ret_val;
2040
2041 if (CDF_FTM_MODE == hdd_get_conparam()) {
2042 hdd_err("Command not allowed in FTM mode");
2043 return -EPERM;
2044 }
2045
2046 if (hdd_ctx_ptr->config->isRoamOffloadEnabled) {
2047 hddLog(LOG1, FL("Key Mgmt Offload is supported"));
2048 wlan_hdd_cfg80211_set_feature(feature_flags,
2049 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2050 }
2051
2052 wlan_hdd_cfg80211_set_feature(feature_flags,
2053 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2054 if (wma_is_scan_simultaneous_capable())
2055 wlan_hdd_cfg80211_set_feature(feature_flags,
2056 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
2057 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2058 NLMSG_HDRLEN);
2059
2060 if (!skb) {
2061 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2062 return -ENOMEM;
2063 }
2064
2065 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2066 sizeof(feature_flags), feature_flags))
2067 goto nla_put_failure;
2068
2069 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
2070 if (CDF_STATUS_SUCCESS == ret) {
2071 if (one_by_one_dbs)
2072 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2073
2074 if (two_by_two_dbs)
2075 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2076
2077 if (!one_by_one_dbs && !two_by_two_dbs)
2078 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2079 } else {
2080 hdd_err("wma_get_dbs_hw_mode failed");
2081 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2082 }
2083
2084 hdd_info("dbs_capability is %d", dbs_capability);
2085
2086 if (nla_put_u32(skb,
2087 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2088 MAX_CONCURRENT_CHAN_ON_24G))
2089 goto nla_put_failure;
2090
2091 if (nla_put_u32(skb,
2092 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2093 MAX_CONCURRENT_CHAN_ON_5G))
2094 goto nla_put_failure;
2095
2096 return cfg80211_vendor_cmd_reply(skb);
2097
2098nla_put_failure:
2099 kfree_skb(skb);
2100 return -EINVAL;
2101}
2102
2103/**
2104 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2105 * @wiphy: pointer to wireless wiphy structure.
2106 * @wdev: pointer to wireless_dev structure.
2107 * @data: Pointer to the data to be passed via vendor interface
2108 * @data_len:Length of the data to be passed
2109 *
2110 * This is called when wlan driver needs to send supported feature set to
2111 * supplicant upon a request/query from the supplicant.
2112 *
2113 * Return: Return the Success or Failure code.
2114 */
2115static int
2116wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2117 struct wireless_dev *wdev,
2118 const void *data, int data_len)
2119{
2120 int ret;
2121
2122 cds_ssr_protect(__func__);
2123 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2124 data, data_len);
2125 cds_ssr_unprotect(__func__);
2126
2127 return ret;
2128}
2129
2130
2131/**
2132 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2133 * @wiphy: The wiphy structure
2134 * @wdev: The wireless device
2135 * @data: Data passed by framework
2136 * @data_len: Parameters to be configured passed as data
2137 *
2138 * The roaming related parameters are configured by the framework
2139 * using this interface.
2140 *
2141 * Return: Return either success or failure code.
2142 */
2143static int
2144__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2145 struct wireless_dev *wdev, const void *data, int data_len)
2146{
2147 struct net_device *dev = wdev->netdev;
2148 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2149 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2150 uint8_t session_id;
2151 struct roam_ext_params roam_params;
2152 uint32_t cmd_type, req_id;
2153 struct nlattr *curr_attr;
2154 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2155 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2156 int rem, i;
2157 uint32_t buf_len = 0;
2158 int ret;
2159
2160 if (CDF_FTM_MODE == hdd_get_conparam()) {
2161 hdd_err("Command not allowed in FTM mode");
2162 return -EPERM;
2163 }
2164
2165 ret = wlan_hdd_validate_context(pHddCtx);
2166 if (0 != ret) {
2167 hddLog(LOGE, FL("HDD context is not valid"));
2168 return -EINVAL;
2169 }
2170
2171 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2172 data, data_len,
2173 NULL)) {
2174 hddLog(LOGE, FL("Invalid ATTR"));
2175 return -EINVAL;
2176 }
2177 /* Parse and fetch Command Type*/
2178 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
2179 hddLog(LOGE, FL("roam cmd type failed"));
2180 goto fail;
2181 }
2182 session_id = pAdapter->sessionId;
2183 cdf_mem_set(&roam_params, sizeof(roam_params), 0);
2184 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2185 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
2186 hddLog(LOGE, FL("attr request id failed"));
2187 goto fail;
2188 }
2189 req_id = nla_get_u32(
2190 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
2191 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id);
2192 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type);
2193 switch (cmd_type) {
2194 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2195 i = 0;
2196 nla_for_each_nested(curr_attr,
2197 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2198 rem) {
2199 if (nla_parse(tb2,
2200 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2201 nla_data(curr_attr), nla_len(curr_attr),
2202 NULL)) {
2203 hddLog(LOGE,
2204 FL("nla_parse failed"));
2205 goto fail;
2206 }
2207 /* Parse and Fetch allowed SSID list*/
2208 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
2209 hddLog(LOGE, FL("attr allowed ssid failed"));
2210 goto fail;
2211 }
2212 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2213 /*
2214 * Upper Layers include a null termination character.
2215 * Check for the actual permissible length of SSID and
2216 * also ensure not to copy the NULL termination
2217 * character to the driver buffer.
2218 */
2219 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2220 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2221 nla_memcpy(
2222 roam_params.ssid_allowed_list[i].ssId,
2223 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2224 buf_len - 1);
2225 roam_params.ssid_allowed_list[i].length =
2226 buf_len - 1;
2227 hddLog(CDF_TRACE_LEVEL_DEBUG,
2228 FL("SSID[%d]: %.*s,length = %d"), i,
2229 roam_params.ssid_allowed_list[i].length,
2230 roam_params.ssid_allowed_list[i].ssId,
2231 roam_params.ssid_allowed_list[i].length);
2232 i++;
2233 } else {
2234 hddLog(LOGE, FL("Invalid buffer length"));
2235 }
2236 }
2237 roam_params.num_ssid_allowed_list = i;
2238 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"),
2239 roam_params.num_ssid_allowed_list);
2240 sme_update_roam_params(pHddCtx->hHal, session_id,
2241 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2242 break;
2243 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2244 /* Parse and fetch 5G Boost Threshold */
2245 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
2246 hddLog(LOGE, FL("5G boost threshold failed"));
2247 goto fail;
2248 }
2249 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2250 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
2251 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Boost Threshold (%d)"),
2252 roam_params.raise_rssi_thresh_5g);
2253 /* Parse and fetch 5G Penalty Threshold */
2254 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
2255 hddLog(LOGE, FL("5G penalty threshold failed"));
2256 goto fail;
2257 }
2258 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2259 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
2260 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Penalty Threshold (%d)"),
2261 roam_params.drop_rssi_thresh_5g);
2262 /* Parse and fetch 5G Boost Factor */
2263 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
2264 hddLog(LOGE, FL("5G boost Factor failed"));
2265 goto fail;
2266 }
2267 roam_params.raise_factor_5g = nla_get_u32(
2268 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
2269 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"),
2270 roam_params.raise_factor_5g);
2271 /* Parse and fetch 5G Penalty factor */
2272 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
2273 hddLog(LOGE, FL("5G Penalty Factor failed"));
2274 goto fail;
2275 }
2276 roam_params.drop_factor_5g = nla_get_u32(
2277 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
2278 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Penalty factor (%d)"),
2279 roam_params.drop_factor_5g);
2280 /* Parse and fetch 5G Max Boost */
2281 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
2282 hddLog(LOGE, FL("5G Max Boost failed"));
2283 goto fail;
2284 }
2285 roam_params.max_raise_rssi_5g = nla_get_u32(
2286 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
2287 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"),
2288 roam_params.max_raise_rssi_5g);
2289 /* Parse and fetch Rssi Diff */
2290 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
2291 hddLog(LOGE, FL("Rssi Diff failed"));
2292 goto fail;
2293 }
2294 roam_params.rssi_diff = nla_get_s32(
2295 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
2296 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"),
2297 roam_params.rssi_diff);
2298 /* Parse and fetch Alert Rssi Threshold */
2299 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
2300 hddLog(LOGE, FL("Alert Rssi Threshold failed"));
2301 goto fail;
2302 }
2303 roam_params.alert_rssi_threshold = nla_get_u32(
2304 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
2305 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Alert RSSI Threshold (%d)"),
2306 roam_params.alert_rssi_threshold);
2307 sme_update_roam_params(pHddCtx->hHal, session_id,
2308 roam_params,
2309 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2310 break;
2311 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2312 /* Parse and fetch Activate Good Rssi Roam */
2313 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
2314 hddLog(LOGE, FL("Activate Good Rssi Roam failed"));
2315 goto fail;
2316 }
2317 roam_params.good_rssi_roam = nla_get_s32(
2318 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
2319 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Activate Good Rssi Roam (%d)"),
2320 roam_params.good_rssi_roam);
2321 sme_update_roam_params(pHddCtx->hHal, session_id,
2322 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2323 break;
2324 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2325 /* Parse and fetch number of preferred BSSID */
2326 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
2327 hddLog(LOGE, FL("attr num of preferred bssid failed"));
2328 goto fail;
2329 }
2330 roam_params.num_bssid_favored = nla_get_u32(
2331 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
2332 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Num of Preferred BSSID (%d)"),
2333 roam_params.num_bssid_favored);
2334 i = 0;
2335 nla_for_each_nested(curr_attr,
2336 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2337 rem) {
2338 if (nla_parse(tb2,
2339 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2340 nla_data(curr_attr), nla_len(curr_attr),
2341 NULL)) {
2342 hddLog(LOGE, FL("nla_parse failed"));
2343 goto fail;
2344 }
2345 /* Parse and fetch MAC address */
2346 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
2347 hddLog(LOGE, FL("attr mac address failed"));
2348 goto fail;
2349 }
2350 nla_memcpy(roam_params.bssid_favored[i],
2351 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
2352 sizeof(tSirMacAddr));
2353 hddLog(CDF_TRACE_LEVEL_DEBUG, MAC_ADDRESS_STR,
2354 MAC_ADDR_ARRAY(roam_params.bssid_favored[i]));
2355 /* Parse and fetch preference factor*/
2356 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
2357 hddLog(LOGE, FL("BSSID Preference score failed"));
2358 goto fail;
2359 }
2360 roam_params.bssid_favored_factor[i] = nla_get_u32(
2361 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
2362 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("BSSID Preference score (%d)"),
2363 roam_params.bssid_favored_factor[i]);
2364 i++;
2365 }
2366 sme_update_roam_params(pHddCtx->hHal, session_id,
2367 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2368 break;
2369 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2370 /* Parse and fetch number of blacklist BSSID */
2371 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
2372 hddLog(LOGE, FL("attr num of blacklist bssid failed"));
2373 goto fail;
2374 }
2375 roam_params.num_bssid_avoid_list = nla_get_u32(
2376 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
2377 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Num of blacklist BSSID (%d)"),
2378 roam_params.num_bssid_avoid_list);
2379 i = 0;
2380 nla_for_each_nested(curr_attr,
2381 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2382 rem) {
2383 if (nla_parse(tb2,
2384 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2385 nla_data(curr_attr), nla_len(curr_attr),
2386 NULL)) {
2387 hddLog(LOGE, FL("nla_parse failed"));
2388 goto fail;
2389 }
2390 /* Parse and fetch MAC address */
2391 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
2392 hddLog(LOGE, FL("attr blacklist addr failed"));
2393 goto fail;
2394 }
2395 nla_memcpy(roam_params.bssid_avoid_list[i],
2396 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
2397 sizeof(tSirMacAddr));
2398 hddLog(CDF_TRACE_LEVEL_DEBUG, MAC_ADDRESS_STR,
2399 MAC_ADDR_ARRAY(
2400 roam_params.bssid_avoid_list[i]));
2401 i++;
2402 }
2403 sme_update_roam_params(pHddCtx->hHal, session_id,
2404 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2405 break;
2406 }
2407 return 0;
2408fail:
2409 return -EINVAL;
2410}
2411
2412/**
2413 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2414 * @wiphy: pointer to wireless wiphy structure.
2415 * @wdev: pointer to wireless_dev structure.
2416 * @data: Pointer to the data to be passed via vendor interface
2417 * @data_len:Length of the data to be passed
2418 *
2419 * Return: Return the Success or Failure code.
2420 */
2421static int
2422wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2423 struct wireless_dev *wdev,
2424 const void *data,
2425 int data_len)
2426{
2427 int ret;
2428
2429 cds_ssr_protect(__func__);
2430 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2431 data, data_len);
2432 cds_ssr_unprotect(__func__);
2433
2434 return ret;
2435}
2436
2437static const struct nla_policy
2438wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2439 +1] = {
2440 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2441};
2442
2443/**
2444 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2445 * @hdd_ctx: HDD context
2446 * @device_mode: device mode
2447 * Return: bool
2448 */
2449static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
2450 device_mode_t device_mode)
2451{
2452 hdd_adapter_t *adapter;
2453 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2454 hdd_ap_ctx_t *ap_ctx;
2455 hdd_station_ctx_t *sta_ctx;
2456 CDF_STATUS cdf_status;
2457
2458 cdf_status = hdd_get_front_adapter(hdd_ctx,
2459 &adapter_node);
2460
2461 while ((NULL != adapter_node) &&
2462 (CDF_STATUS_SUCCESS == cdf_status)) {
2463 adapter = adapter_node->pAdapter;
2464
2465 if ((device_mode == adapter->device_mode) &&
2466 (device_mode == WLAN_HDD_SOFTAP)) {
2467 ap_ctx =
2468 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2469
2470 /*
2471 * if there is SAP already running on DFS channel,
2472 * do not disable scan on dfs channels. Note that
2473 * with SAP on DFS, there cannot be conurrency on
2474 * single radio. But then we can have multiple
2475 * radios !!
2476 */
2477 if (CHANNEL_STATE_DFS ==
2478 cds_get_channel_state(
2479 ap_ctx->operatingChannel)) {
2480 hddLog(CDF_TRACE_LEVEL_ERROR,
2481 FL("SAP running on DFS channel"));
2482 return true;
2483 }
2484 }
2485
2486 if ((device_mode == adapter->device_mode) &&
2487 (device_mode == WLAN_HDD_INFRA_STATION)) {
2488 sta_ctx =
2489 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2490
2491 /*
2492 * if STA is already connected on DFS channel,
2493 * do not disable scan on dfs channels
2494 */
2495 if (hdd_conn_is_connected(sta_ctx) &&
2496 (CHANNEL_STATE_DFS ==
2497 cds_get_channel_state(
2498 sta_ctx->conn_info.operationChannel))) {
2499 hddLog(LOGE,
2500 FL("client connected on DFS channel"));
2501 return true;
2502 }
2503 }
2504
2505 cdf_status = hdd_get_next_adapter(hdd_ctx,
2506 adapter_node,
2507 &next);
2508 adapter_node = next;
2509 }
2510
2511 return false;
2512}
2513
2514/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002515 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2516 * @hdd_ctx: HDD context within host driver
2517 * @adapter: Adapter pointer
2518 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2519 *
2520 * Loops through devices to see who is operating on DFS channels
2521 * and then disables/enables DFS channels by calling SME API.
2522 * Fails the disable request if any device is active on a DFS channel.
2523 *
2524 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002526
2527int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2528 hdd_adapter_t *adapter,
2529 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002531 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 CDF_STATUS status;
2533 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534
2535 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2536 if (no_dfs_flag) {
2537 status = wlan_hdd_check_dfs_channel_for_adapter(
2538 hdd_ctx, WLAN_HDD_INFRA_STATION);
2539
2540 if (true == status)
2541 return -EOPNOTSUPP;
2542
2543 status = wlan_hdd_check_dfs_channel_for_adapter(
2544 hdd_ctx, WLAN_HDD_SOFTAP);
2545
2546 if (true == status)
2547 return -EOPNOTSUPP;
2548 }
2549
2550 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2551
2552 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2553
2554 /*
2555 * call the SME API to tunnel down the new channel list
2556 * to the firmware
2557 */
2558 status = sme_handle_dfs_chan_scan(
2559 h_hal, hdd_ctx->config->enableDFSChnlScan);
2560
2561 if (CDF_STATUS_SUCCESS == status) {
2562 ret_val = 0;
2563
2564 /*
2565 * Clear the SME scan cache also. Note that the
2566 * clearing of scan results is independent of session;
2567 * so no need to iterate over
2568 * all sessions
2569 */
2570 status = sme_scan_flush_result(h_hal);
2571 if (CDF_STATUS_SUCCESS != status)
2572 ret_val = -EPERM;
2573 }
2574
2575 } else {
2576 hddLog(CDF_TRACE_LEVEL_INFO,
2577 FL(" the DFS flag has not changed"));
2578 ret_val = 0;
2579 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002580 return ret_val;
2581}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002583/**
2584 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2585 * @wiphy: corestack handler
2586 * @wdev: wireless device
2587 * @data: data
2588 * @data_len: data length
2589 * Return: success(0) or reason code for failure
2590 */
2591static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2592 struct wireless_dev *wdev,
2593 const void *data,
2594 int data_len)
2595{
2596 struct net_device *dev = wdev->netdev;
2597 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2598 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2599 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2600 int ret_val;
2601 uint32_t no_dfs_flag = 0;
2602
2603 ENTER();
2604 ret_val = wlan_hdd_validate_context(hdd_ctx);
2605
2606 if (ret_val) {
2607 hdd_err("HDD context is not valid");
2608 return ret_val;
2609 }
2610
2611 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2612 data, data_len,
2613 wlan_hdd_set_no_dfs_flag_config_policy)) {
2614 hdd_err("invalid attr");
2615 return -EINVAL;
2616 }
2617
2618 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2619 hdd_err("attr dfs flag failed");
2620 return -EINVAL;
2621 }
2622
2623 no_dfs_flag = nla_get_u32(
2624 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2625
2626 hddLog(LOG1, FL(" DFS flag = %d"), no_dfs_flag);
2627
2628 if (no_dfs_flag > 1) {
2629 hddLog(LOGE, FL("invalid value of dfs flag"));
2630 return -EINVAL;
2631 }
2632
2633 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2634 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002635 return ret_val;
2636}
2637
2638/**
2639 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2640 *
2641 * @wiphy: wiphy device pointer
2642 * @wdev: wireless device pointer
2643 * @data: Vendof command data buffer
2644 * @data_len: Buffer length
2645 *
2646 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2647 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2648 *
2649 * Return: EOK or other error codes.
2650 */
2651
2652static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2653 struct wireless_dev *wdev,
2654 const void *data,
2655 int data_len)
2656{
2657 int ret;
2658
2659 cds_ssr_protect(__func__);
2660 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2661 data, data_len);
2662 cds_ssr_unprotect(__func__);
2663
2664 return ret;
2665}
2666
2667#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2668/**
2669 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2670 * @wiphy: pointer to wireless wiphy structure.
2671 * @wdev: pointer to wireless_dev structure.
2672 * @data: Pointer to the Key data
2673 * @data_len:Length of the data passed
2674 *
2675 * This is called when wlan driver needs to save the keys received via
2676 * vendor specific command.
2677 *
2678 * Return: Return the Success or Failure code.
2679 */
2680static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2681 struct wireless_dev *wdev,
2682 const void *data, int data_len)
2683{
2684 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
2685 struct net_device *dev = wdev->netdev;
2686 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
2687 hdd_context_t *hdd_ctx_ptr;
2688 int status;
2689
2690 if (CDF_FTM_MODE == hdd_get_conparam()) {
2691 hdd_err("Command not allowed in FTM mode");
2692 return -EPERM;
2693 }
2694
2695 if ((data == NULL) || (data_len == 0) ||
2696 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
2697 hddLog(LOGE, FL("Invalid data"));
2698 return -EINVAL;
2699 }
2700
2701 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
2702 if (!hdd_ctx_ptr) {
2703 hddLog(LOGE, FL("HDD context is null"));
2704 return -EINVAL;
2705 }
2706
2707 status = wlan_hdd_validate_context(hdd_ctx_ptr);
2708 if (0 != status) {
2709 hddLog(LOGE, FL("HDD context is invalid"));
2710 return status;
2711 }
2712 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
2713 hdd_adapter_ptr->sessionId,
2714 true);
2715 cdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
2716 cdf_mem_copy(local_pmk, data, data_len);
2717 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
2718 hdd_adapter_ptr->sessionId, local_pmk, data_len);
2719 return 0;
2720}
2721
2722/**
2723 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2724 * @wiphy: pointer to wireless wiphy structure.
2725 * @wdev: pointer to wireless_dev structure.
2726 * @data: Pointer to the Key data
2727 * @data_len:Length of the data passed
2728 *
2729 * This is called when wlan driver needs to save the keys received via
2730 * vendor specific command.
2731 *
2732 * Return: Return the Success or Failure code.
2733 */
2734static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2735 struct wireless_dev *wdev,
2736 const void *data, int data_len)
2737{
2738 int ret;
2739
2740 cds_ssr_protect(__func__);
2741 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
2742 cds_ssr_unprotect(__func__);
2743
2744 return ret;
2745}
2746
2747static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
2748 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
2749 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
2750 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
2751};
2752
2753/**
2754 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2755 * @wiphy: pointer to wireless wiphy structure.
2756 * @wdev: pointer to wireless_dev structure.
2757 * @data: Pointer to the data to be passed via vendor interface
2758 * @data_len:Length of the data to be passed
2759 *
2760 * This is called when wlan driver needs to send wifi driver related info
2761 * (driver/fw version) to the user space application upon request.
2762 *
2763 * Return: Return the Success or Failure code.
2764 */
2765static int
2766__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2767 struct wireless_dev *wdev,
2768 const void *data, int data_len)
2769{
2770 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2771 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
2772 tSirVersionString version;
2773 uint32_t version_len;
2774 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
2775 uint8_t attr;
2776 int status;
2777 struct sk_buff *reply_skb = NULL;
2778
2779 if (CDF_FTM_MODE == hdd_get_conparam()) {
2780 hdd_err("Command not allowed in FTM mode");
2781 return -EPERM;
2782 }
2783
2784 status = wlan_hdd_validate_context(hdd_ctx);
2785 if (0 != status) {
2786 hddLog(LOGE, FL("HDD context is not valid"));
2787 return -EINVAL;
2788 }
2789
2790 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
2791 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
2792 hddLog(LOGE, FL("WIFI_INFO_GET NL CMD parsing failed"));
2793 return -EINVAL;
2794 }
2795
2796 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
2797 hddLog(LOG1, FL("Rcvd req for Driver version"));
2798 strlcpy(version, QWLAN_VERSIONSTR, sizeof(version));
2799 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
2800 } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
2801 hddLog(LOG1, FL("Rcvd req for FW version"));
2802 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
2803 &crmid);
2804 snprintf(version, sizeof(version), "%d:%d:%d:%d",
2805 major_spid, minor_spid, siid, crmid);
2806 attr = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
2807 } else {
2808 hddLog(LOGE, FL("Invalid attribute in get wifi info request"));
2809 return -EINVAL;
2810 }
2811
2812 version_len = strlen(version);
2813 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2814 version_len + NLA_HDRLEN + NLMSG_HDRLEN);
2815 if (!reply_skb) {
2816 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2817 return -ENOMEM;
2818 }
2819
2820 if (nla_put(reply_skb, attr, version_len, version)) {
2821 hddLog(LOGE, FL("nla put fail"));
2822 kfree_skb(reply_skb);
2823 return -EINVAL;
2824 }
2825
2826 return cfg80211_vendor_cmd_reply(reply_skb);
2827}
2828
2829/**
2830 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2831 * @wiphy: pointer to wireless wiphy structure.
2832 * @wdev: pointer to wireless_dev structure.
2833 * @data: Pointer to the data to be passed via vendor interface
2834 * @data_len:Length of the data to be passed
2835 *
2836 * This is called when wlan driver needs to send wifi driver related info
2837 * (driver/fw version) to the user space application upon request.
2838 *
2839 * Return: Return the Success or Failure code.
2840 */
2841static int
2842wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2843 struct wireless_dev *wdev,
2844 const void *data, int data_len)
2845{
2846 int ret;
2847
2848 cds_ssr_protect(__func__);
2849 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
2850 cds_ssr_unprotect(__func__);
2851
2852 return ret;
2853}
2854
2855/**
2856 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
2857 * @wiphy: pointer to wireless wiphy structure.
2858 * @wdev: pointer to wireless_dev structure.
2859 * @data: Pointer to the data to be passed via vendor interface
2860 * @data_len:Length of the data to be passed
2861 *
2862 * This is called by userspace to know the supported logger features
2863 *
2864 * Return: Return the Success or Failure code.
2865 */
2866static int
2867__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
2868 struct wireless_dev *wdev,
2869 const void *data, int data_len)
2870{
2871 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2872 int status;
2873 uint32_t features;
2874 struct sk_buff *reply_skb = NULL;
2875
2876 if (CDF_FTM_MODE == hdd_get_conparam()) {
2877 hdd_err("Command not allowed in FTM mode");
2878 return -EPERM;
2879 }
2880
2881 status = wlan_hdd_validate_context(hdd_ctx);
2882 if (0 != status) {
2883 hddLog(LOGE, FL("HDD context is not valid"));
2884 return -EINVAL;
2885 }
2886
2887 features = 0;
2888
2889 if (hdd_is_memdump_supported())
2890 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
2891 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
2892 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
2893 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
2894
2895 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2896 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
2897 if (!reply_skb) {
2898 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2899 return -ENOMEM;
2900 }
2901
2902 hddLog(LOG1, FL("Supported logger features: 0x%0x"), features);
2903 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
2904 features)) {
2905 hddLog(LOGE, FL("nla put fail"));
2906 kfree_skb(reply_skb);
2907 return -EINVAL;
2908 }
2909
2910 return cfg80211_vendor_cmd_reply(reply_skb);
2911}
2912
2913/**
2914 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
2915 * @wiphy: pointer to wireless wiphy structure.
2916 * @wdev: pointer to wireless_dev structure.
2917 * @data: Pointer to the data to be passed via vendor interface
2918 * @data_len:Length of the data to be passed
2919 *
2920 * This is called by userspace to know the supported logger features
2921 *
2922 * Return: Return the Success or Failure code.
2923 */
2924static int
2925wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
2926 struct wireless_dev *wdev,
2927 const void *data, int data_len)
2928{
2929 int ret;
2930
2931 cds_ssr_protect(__func__);
2932 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
2933 data, data_len);
2934 cds_ssr_unprotect(__func__);
2935
2936 return ret;
2937}
2938
2939/**
2940 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
2941 * @hdd_ctx_ptr: pointer to HDD Context.
2942 * @bssid: pointer to bssid of roamed AP.
2943 * @req_rsn_ie: Pointer to request RSN IE
2944 * @req_rsn_len: Length of the request RSN IE
2945 * @rsp_rsn_ie: Pointer to response RSN IE
2946 * @rsp_rsn_len: Length of the response RSN IE
2947 * @roam_info_ptr: Pointer to the roaming related information
2948 *
2949 * This is called when wlan driver needs to send the roaming and
2950 * authorization information after roaming.
2951 *
2952 * The information that would be sent is the request RSN IE, response
2953 * RSN IE and BSSID of the newly roamed AP.
2954 *
2955 * If the Authorized status is authenticated, then additional parameters
2956 * like PTK's KCK and KEK and Replay Counter would also be passed to the
2957 * supplicant.
2958 *
2959 * The supplicant upon receiving this event would ignore the legacy
2960 * cfg80211_roamed call and use the entire information from this event.
2961 * The cfg80211_roamed should still co-exist since the kernel will
2962 * make use of the parameters even if the supplicant ignores it.
2963 *
2964 * Return: Return the Success or Failure code.
2965 */
2966int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
2967 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
2968 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
2969{
2970 struct sk_buff *skb = NULL;
2971 ENTER();
2972
2973 if (wlan_hdd_validate_context(hdd_ctx_ptr)) {
2974 hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid "));
2975 return -EINVAL;
2976 }
2977
2978 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
2979 NULL,
2980 ETH_ALEN + req_rsn_len + rsp_rsn_len +
2981 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
2982 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
2983 (7 * NLMSG_HDRLEN),
2984 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
2985 GFP_KERNEL);
2986
2987 if (!skb) {
2988 hddLog(CDF_TRACE_LEVEL_ERROR,
2989 FL("cfg80211_vendor_event_alloc failed"));
2990 return -EINVAL;
2991 }
2992
2993 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
2994 ETH_ALEN, bssid) ||
2995 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
2996 req_rsn_len, req_rsn_ie) ||
2997 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
2998 rsp_rsn_len, rsp_rsn_ie)) {
2999 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
3000 goto nla_put_failure;
3001 }
3002 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"),
3003 roam_info_ptr->synchAuthStatus);
3004 if (roam_info_ptr->synchAuthStatus ==
3005 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
3006 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's"));
3007 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3008 true) ||
3009 nla_put(skb,
3010 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3011 SIR_REPLAY_CTR_LEN, roam_info_ptr->replay_ctr)
3012 || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3013 SIR_KCK_KEY_LEN, roam_info_ptr->kck)
3014 || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3015 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3016 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
3017 goto nla_put_failure;
3018 }
3019 } else {
3020 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's"));
3021 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3022 false)) {
3023 hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
3024 goto nla_put_failure;
3025 }
3026 }
3027
3028 cfg80211_vendor_event(skb, GFP_KERNEL);
3029 return 0;
3030
3031nla_put_failure:
3032 kfree_skb(skb);
3033 return -EINVAL;
3034}
3035#endif
3036
3037static const struct nla_policy
3038wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3039
3040 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3041 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3042 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3043};
3044
3045
3046/**
3047 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3048 * vendor command
3049 *
3050 * @wiphy: wiphy device pointer
3051 * @wdev: wireless device pointer
3052 * @data: Vendor command data buffer
3053 * @data_len: Buffer length
3054 *
3055 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3056 *
3057 * Return: Error code.
3058 */
3059static int
3060__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3061 struct wireless_dev *wdev,
3062 const void *data,
3063 int data_len)
3064{
3065 struct net_device *dev = wdev->netdev;
3066 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3067 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3068 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3069 int ret_val = 0;
3070 u32 modulated_dtim;
3071 u16 stats_avg_factor;
3072 u32 guard_time;
3073 CDF_STATUS status;
3074
3075 if (CDF_FTM_MODE == hdd_get_conparam()) {
3076 hdd_err("Command not allowed in FTM mode");
3077 return -EPERM;
3078 }
3079
3080 ret_val = wlan_hdd_validate_context(hdd_ctx);
3081 if (ret_val) {
3082 hddLog(LOGE, FL("HDD context is not valid"));
3083 return ret_val;
3084 }
3085
3086 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3087 data, data_len,
3088 wlan_hdd_wifi_config_policy)) {
3089 hddLog(LOGE, FL("invalid attr"));
3090 return -EINVAL;
3091 }
3092
3093 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3094 modulated_dtim = nla_get_u32(
3095 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3096
3097 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3098 adapter->sessionId,
3099 modulated_dtim);
3100
3101 if (CDF_STATUS_SUCCESS != status)
3102 ret_val = -EPERM;
3103 }
3104
3105 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3106 stats_avg_factor = nla_get_u16(
3107 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3108 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3109 adapter->sessionId,
3110 stats_avg_factor);
3111
3112 if (CDF_STATUS_SUCCESS != status)
3113 ret_val = -EPERM;
3114 }
3115
3116
3117 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3118 guard_time = nla_get_u32(
3119 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3120 status = sme_configure_guard_time(hdd_ctx->hHal,
3121 adapter->sessionId,
3122 guard_time);
3123
3124 if (CDF_STATUS_SUCCESS != status)
3125 ret_val = -EPERM;
3126 }
3127
3128 return ret_val;
3129}
3130
3131/**
3132 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3133 * vendor command
3134 *
3135 * @wiphy: wiphy device pointer
3136 * @wdev: wireless device pointer
3137 * @data: Vendor command data buffer
3138 * @data_len: Buffer length
3139 *
3140 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3141 *
3142 * Return: EOK or other error codes.
3143 */
3144static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3145 struct wireless_dev *wdev,
3146 const void *data,
3147 int data_len)
3148{
3149 int ret;
3150
3151 cds_ssr_protect(__func__);
3152 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3153 data, data_len);
3154 cds_ssr_unprotect(__func__);
3155
3156 return ret;
3157}
3158
3159static const struct
3160nla_policy
3161qca_wlan_vendor_wifi_logger_start_policy
3162[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3163 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3164 = {.type = NLA_U32 },
3165 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3166 = {.type = NLA_U32 },
3167 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3168 = {.type = NLA_U32 },
3169};
3170
3171/**
3172 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3173 * or disable the collection of packet statistics from the firmware
3174 * @wiphy: WIPHY structure pointer
3175 * @wdev: Wireless device structure pointer
3176 * @data: Pointer to the data received
3177 * @data_len: Length of the data received
3178 *
3179 * This function enables or disables the collection of packet statistics from
3180 * the firmware
3181 *
3182 * Return: 0 on success and errno on failure
3183 */
3184static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3185 struct wireless_dev *wdev,
3186 const void *data,
3187 int data_len)
3188{
3189 CDF_STATUS status;
3190 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3191 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
3192 struct sir_wifi_start_log start_log;
3193
3194 if (CDF_FTM_MODE == hdd_get_conparam()) {
3195 hdd_err("Command not allowed in FTM mode");
3196 return -EPERM;
3197 }
3198
3199 status = wlan_hdd_validate_context(hdd_ctx);
3200 if (0 != status) {
3201 hddLog(LOGE, FL("HDD context is not valid"));
3202 return -EINVAL;
3203 }
3204
3205 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
3206 data, data_len,
3207 qca_wlan_vendor_wifi_logger_start_policy)) {
3208 hddLog(LOGE, FL("Invalid attribute"));
3209 return -EINVAL;
3210 }
3211
3212 /* Parse and fetch ring id */
3213 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
3214 hddLog(LOGE, FL("attr ATTR failed"));
3215 return -EINVAL;
3216 }
3217 start_log.ring_id = nla_get_u32(
3218 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
3219 hddLog(LOGE, FL("Ring ID=%d"), start_log.ring_id);
3220
3221 /* Parse and fetch verbose level */
3222 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
3223 hddLog(LOGE, FL("attr verbose_level failed"));
3224 return -EINVAL;
3225 }
3226 start_log.verbose_level = nla_get_u32(
3227 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
3228 hddLog(LOGE, FL("verbose_level=%d"), start_log.verbose_level);
3229
3230 /* Parse and fetch flag */
3231 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
3232 hddLog(LOGE, FL("attr flag failed"));
3233 return -EINVAL;
3234 }
3235 start_log.flag = nla_get_u32(
3236 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
3237 hddLog(LOGE, FL("flag=%d"), start_log.flag);
3238
3239 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
3240
3241 if (start_log.ring_id == RING_ID_WAKELOCK) {
3242 /* Start/stop wakelock events */
3243 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
3244 cds_set_wakelock_logging(true);
3245 else
3246 cds_set_wakelock_logging(false);
3247 return 0;
3248 }
3249
3250 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
3251 if (!CDF_IS_STATUS_SUCCESS(status)) {
3252 hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"),
3253 status);
3254 return -EINVAL;
3255 }
3256 return 0;
3257}
3258
3259/**
3260 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
3261 * or disable the collection of packet statistics from the firmware
3262 * @wiphy: WIPHY structure pointer
3263 * @wdev: Wireless device structure pointer
3264 * @data: Pointer to the data received
3265 * @data_len: Length of the data received
3266 *
3267 * This function is used to enable or disable the collection of packet
3268 * statistics from the firmware
3269 *
3270 * Return: 0 on success and errno on failure
3271 */
3272static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3273 struct wireless_dev *wdev,
3274 const void *data,
3275 int data_len)
3276{
3277 int ret = 0;
3278
3279 cds_ssr_protect(__func__);
3280 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
3281 wdev, data, data_len);
3282 cds_ssr_unprotect(__func__);
3283
3284 return ret;
3285}
3286
3287static const struct
3288nla_policy
3289qca_wlan_vendor_wifi_logger_get_ring_data_policy
3290[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
3291 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
3292 = {.type = NLA_U32 },
3293};
3294
3295/**
3296 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
3297 * @wiphy: WIPHY structure pointer
3298 * @wdev: Wireless device structure pointer
3299 * @data: Pointer to the data received
3300 * @data_len: Length of the data received
3301 *
3302 * This function is used to flush or retrieve the per packet statistics from
3303 * the driver
3304 *
3305 * Return: 0 on success and errno on failure
3306 */
3307static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3308 struct wireless_dev *wdev,
3309 const void *data,
3310 int data_len)
3311{
3312 CDF_STATUS status;
3313 uint32_t ring_id;
3314 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3315 struct nlattr *tb
3316 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
3317
3318 if (CDF_FTM_MODE == hdd_get_conparam()) {
3319 hdd_err("Command not allowed in FTM mode");
3320 return -EPERM;
3321 }
3322
3323 status = wlan_hdd_validate_context(hdd_ctx);
3324 if (0 != status) {
3325 hddLog(LOGE, FL("HDD context is not valid"));
3326 return -EINVAL;
3327 }
3328
3329 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
3330 data, data_len,
3331 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
3332 hddLog(LOGE, FL("Invalid attribute"));
3333 return -EINVAL;
3334 }
3335
3336 /* Parse and fetch ring id */
3337 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
3338 hddLog(LOGE, FL("attr ATTR failed"));
3339 return -EINVAL;
3340 }
3341
3342 ring_id = nla_get_u32(
3343 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
3344
3345 if (ring_id == RING_ID_PER_PACKET_STATS) {
3346 wlan_logging_set_per_pkt_stats();
3347 hddLog(LOG1, FL("Flushing/Retrieving packet stats"));
3348 }
3349
3350 hddLog(LOG1, FL("Bug report triggered by framework"));
3351
3352 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
3353 WLAN_LOG_INDICATOR_FRAMEWORK,
3354 WLAN_LOG_REASON_CODE_UNUSED);
3355 if (CDF_STATUS_SUCCESS != status) {
3356 hddLog(LOGE, FL("Failed to trigger bug report"));
3357 return -EINVAL;
3358 }
3359
3360 return 0;
3361}
3362
3363/**
3364 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
3365 * @wiphy: WIPHY structure pointer
3366 * @wdev: Wireless device structure pointer
3367 * @data: Pointer to the data received
3368 * @data_len: Length of the data received
3369 *
3370 * This function is used to flush or retrieve the per packet statistics from
3371 * the driver
3372 *
3373 * Return: 0 on success and errno on failure
3374 */
3375static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3376 struct wireless_dev *wdev,
3377 const void *data,
3378 int data_len)
3379{
3380 int ret = 0;
3381
3382 cds_ssr_protect(__func__);
3383 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
3384 wdev, data, data_len);
3385 cds_ssr_unprotect(__func__);
3386
3387 return ret;
3388}
3389
3390#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
3391/**
3392 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
3393 * @hdd_ctx: HDD context
3394 * @request_id: [input] request id
3395 * @pattern_id: [output] pattern id
3396 *
3397 * This function loops through request id to pattern id array
3398 * if the slot is available, store the request id and return pattern id
3399 * if entry exists, return the pattern id
3400 *
3401 * Return: 0 on success and errno on failure
3402 */
3403static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3404 uint32_t request_id,
3405 uint8_t *pattern_id)
3406{
3407 uint32_t i;
3408
3409 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3410 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3411 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
3412 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
3413 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3414 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3415 return 0;
3416 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
3417 request_id) {
3418 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3419 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3420 return 0;
3421 }
3422 }
3423 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3424 return -EINVAL;
3425}
3426
3427/**
3428 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
3429 * @hdd_ctx: HDD context
3430 * @request_id: [input] request id
3431 * @pattern_id: [output] pattern id
3432 *
3433 * This function loops through request id to pattern id array
3434 * reset request id to 0 (slot available again) and
3435 * return pattern id
3436 *
3437 * Return: 0 on success and errno on failure
3438 */
3439static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3440 uint32_t request_id,
3441 uint8_t *pattern_id)
3442{
3443 uint32_t i;
3444
3445 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3446 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3447 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
3448 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
3449 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3450 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3451 return 0;
3452 }
3453 }
3454 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3455 return -EINVAL;
3456}
3457
3458
3459/*
3460 * define short names for the global vendor params
3461 * used by __wlan_hdd_cfg80211_offloaded_packets()
3462 */
3463#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
3464#define PARAM_REQUEST_ID \
3465 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
3466#define PARAM_CONTROL \
3467 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
3468#define PARAM_IP_PACKET \
3469 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
3470#define PARAM_SRC_MAC_ADDR \
3471 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
3472#define PARAM_DST_MAC_ADDR \
3473 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
3474#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
3475
3476/**
3477 * wlan_hdd_add_tx_ptrn() - add tx pattern
3478 * @adapter: adapter pointer
3479 * @hdd_ctx: hdd context
3480 * @tb: nl attributes
3481 *
3482 * This function reads the NL attributes and forms a AddTxPtrn message
3483 * posts it to SME.
3484 *
3485 */
3486static int
3487wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3488 struct nlattr **tb)
3489{
3490 struct sSirAddPeriodicTxPtrn *add_req;
3491 CDF_STATUS status;
3492 uint32_t request_id, ret, len;
3493 uint8_t pattern_id = 0;
3494 struct cdf_mac_addr dst_addr;
3495 uint16_t eth_type = htons(ETH_P_IP);
3496
3497 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3498 hddLog(LOGE, FL("Not in Connected state!"));
3499 return -ENOTSUPP;
3500 }
3501
3502 add_req = cdf_mem_malloc(sizeof(*add_req));
3503 if (!add_req) {
3504 hddLog(LOGE, FL("memory allocation failed"));
3505 return -ENOMEM;
3506 }
3507
3508 /* Parse and fetch request Id */
3509 if (!tb[PARAM_REQUEST_ID]) {
3510 hddLog(LOGE, FL("attr request id failed"));
3511 goto fail;
3512 }
3513
3514 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3515 if (request_id == MAX_REQUEST_ID) {
3516 hddLog(LOGE, FL("request_id cannot be MAX"));
3517 return -EINVAL;
3518 }
3519 hddLog(LOG1, FL("Request Id: %u"), request_id);
3520
3521 if (!tb[PARAM_PERIOD]) {
3522 hddLog(LOGE, FL("attr period failed"));
3523 goto fail;
3524 }
3525 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
3526 hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs);
3527 if (add_req->usPtrnIntervalMs == 0) {
3528 hddLog(LOGE, FL("Invalid interval zero, return failure"));
3529 goto fail;
3530 }
3531
3532 if (!tb[PARAM_SRC_MAC_ADDR]) {
3533 hddLog(LOGE, FL("attr source mac address failed"));
3534 goto fail;
3535 }
3536 nla_memcpy(add_req->macAddress, tb[PARAM_SRC_MAC_ADDR],
3537 CDF_MAC_ADDR_SIZE);
3538 hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR,
3539 MAC_ADDR_ARRAY(add_req->macAddress));
3540
3541 if (memcmp(add_req->macAddress, adapter->macAddressCurrent.bytes,
3542 CDF_MAC_ADDR_SIZE)) {
3543 hddLog(LOGE, FL("input src mac address and connected ap bssid are different"));
3544 goto fail;
3545 }
3546
3547 if (!tb[PARAM_DST_MAC_ADDR]) {
3548 hddLog(LOGE, FL("attr dst mac address failed"));
3549 goto fail;
3550 }
3551 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], CDF_MAC_ADDR_SIZE);
3552 hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR,
3553 MAC_ADDR_ARRAY(dst_addr.bytes));
3554
3555 if (!tb[PARAM_IP_PACKET]) {
3556 hddLog(LOGE, FL("attr ip packet failed"));
3557 goto fail;
3558 }
3559 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
3560 hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize);
3561
3562 if (add_req->ucPtrnSize < 0 ||
3563 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
3564 ETH_HLEN)) {
3565 hddLog(LOGE, FL("Invalid IP packet len: %d"),
3566 add_req->ucPtrnSize);
3567 goto fail;
3568 }
3569
3570 len = 0;
3571 cdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, CDF_MAC_ADDR_SIZE);
3572 len += CDF_MAC_ADDR_SIZE;
3573 cdf_mem_copy(&add_req->ucPattern[len], add_req->macAddress,
3574 CDF_MAC_ADDR_SIZE);
3575 len += CDF_MAC_ADDR_SIZE;
3576 cdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
3577 len += 2;
3578
3579 /*
3580 * This is the IP packet, add 14 bytes Ethernet (802.3) header
3581 * ------------------------------------------------------------
3582 * | 14 bytes Ethernet (802.3) header | IP header and payload |
3583 * ------------------------------------------------------------
3584 */
3585 cdf_mem_copy(&add_req->ucPattern[len],
3586 nla_data(tb[PARAM_IP_PACKET]),
3587 add_req->ucPtrnSize);
3588 add_req->ucPtrnSize += len;
3589
3590 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3591 if (ret) {
3592 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3593 goto fail;
3594 }
3595 add_req->ucPtrnId = pattern_id;
3596 hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId);
3597
3598 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
3599 if (!CDF_IS_STATUS_SUCCESS(status)) {
3600 hddLog(LOGE,
3601 FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status);
3602 goto fail;
3603 }
3604
3605 EXIT();
3606 cdf_mem_free(add_req);
3607 return 0;
3608
3609fail:
3610 cdf_mem_free(add_req);
3611 return -EINVAL;
3612}
3613
3614/**
3615 * wlan_hdd_del_tx_ptrn() - delete tx pattern
3616 * @adapter: adapter pointer
3617 * @hdd_ctx: hdd context
3618 * @tb: nl attributes
3619 *
3620 * This function reads the NL attributes and forms a DelTxPtrn message
3621 * posts it to SME.
3622 *
3623 */
3624static int
3625wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3626 struct nlattr **tb)
3627{
3628 struct sSirDelPeriodicTxPtrn *del_req;
3629 CDF_STATUS status;
3630 uint32_t request_id, ret;
3631 uint8_t pattern_id = 0;
3632
3633 /* Parse and fetch request Id */
3634 if (!tb[PARAM_REQUEST_ID]) {
3635 hddLog(LOGE, FL("attr request id failed"));
3636 return -EINVAL;
3637 }
3638 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3639 if (request_id == MAX_REQUEST_ID) {
3640 hddLog(LOGE, FL("request_id cannot be MAX"));
3641 return -EINVAL;
3642 }
3643
3644 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3645 if (ret) {
3646 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3647 return -EINVAL;
3648 }
3649
3650 del_req = cdf_mem_malloc(sizeof(*del_req));
3651 if (!del_req) {
3652 hddLog(LOGE, FL("memory allocation failed"));
3653 return -ENOMEM;
3654 }
3655
3656 cdf_mem_copy(del_req->macAddress, adapter->macAddressCurrent.bytes,
3657 CDF_MAC_ADDR_SIZE);
3658 hddLog(LOG1, MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->macAddress));
3659 del_req->ucPtrnId = pattern_id;
3660 hddLog(LOG1, FL("Request Id: %u Pattern id: %d"),
3661 request_id, del_req->ucPtrnId);
3662
3663 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
3664 if (!CDF_IS_STATUS_SUCCESS(status)) {
3665 hddLog(LOGE,
3666 FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status);
3667 goto fail;
3668 }
3669
3670 EXIT();
3671 cdf_mem_free(del_req);
3672 return 0;
3673
3674fail:
3675 cdf_mem_free(del_req);
3676 return -EINVAL;
3677}
3678
3679
3680/**
3681 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
3682 * @wiphy: Pointer to wireless phy
3683 * @wdev: Pointer to wireless device
3684 * @data: Pointer to data
3685 * @data_len: Data length
3686 *
3687 * Return: 0 on success, negative errno on failure
3688 */
3689static int
3690__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3691 struct wireless_dev *wdev,
3692 const void *data,
3693 int data_len)
3694{
3695 struct net_device *dev = wdev->netdev;
3696 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3697 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3698 struct nlattr *tb[PARAM_MAX + 1];
3699 uint8_t control;
3700 int ret;
3701 static const struct nla_policy policy[PARAM_MAX + 1] = {
3702 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3703 [PARAM_CONTROL] = { .type = NLA_U32 },
3704 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
3705 .len = CDF_MAC_ADDR_SIZE },
3706 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
3707 .len = CDF_MAC_ADDR_SIZE },
3708 [PARAM_PERIOD] = { .type = NLA_U32 },
3709 };
3710
3711 ENTER();
3712
3713 if (CDF_FTM_MODE == hdd_get_conparam()) {
3714 hdd_err("Command not allowed in FTM mode");
3715 return -EPERM;
3716 }
3717
3718 ret = wlan_hdd_validate_context(hdd_ctx);
3719 if (0 != ret) {
3720 hddLog(LOGE, FL("HDD context is not valid"));
3721 return ret;
3722 }
3723
3724 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
3725 hddLog(LOGE,
3726 FL("Periodic Tx Pattern Offload feature is not supported in FW!"));
3727 return -ENOTSUPP;
3728 }
3729
3730 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3731 hddLog(LOGE, FL("Invalid ATTR"));
3732 return -EINVAL;
3733 }
3734
3735 if (!tb[PARAM_CONTROL]) {
3736 hddLog(LOGE, FL("attr control failed"));
3737 return -EINVAL;
3738 }
3739 control = nla_get_u32(tb[PARAM_CONTROL]);
3740 hddLog(LOG1, FL("Control: %d"), control);
3741
3742 if (control == WLAN_START_OFFLOADED_PACKETS)
3743 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
3744 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
3745 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
3746 else {
3747 hddLog(LOGE, FL("Invalid control: %d"), control);
3748 return -EINVAL;
3749 }
3750}
3751
3752/*
3753 * done with short names for the global vendor params
3754 * used by __wlan_hdd_cfg80211_offloaded_packets()
3755 */
3756#undef PARAM_MAX
3757#undef PARAM_REQUEST_ID
3758#undef PARAM_CONTROL
3759#undef PARAM_IP_PACKET
3760#undef PARAM_SRC_MAC_ADDR
3761#undef PARAM_DST_MAC_ADDR
3762#undef PARAM_PERIOD
3763
3764/**
3765 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
3766 * @wiphy: wiphy structure pointer
3767 * @wdev: Wireless device structure pointer
3768 * @data: Pointer to the data received
3769 * @data_len: Length of @data
3770 *
3771 * Return: 0 on success; errno on failure
3772 */
3773static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
3774 struct wireless_dev *wdev,
3775 const void *data,
3776 int data_len)
3777{
3778 int ret = 0;
3779
3780 cds_ssr_protect(__func__);
3781 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
3782 wdev, data, data_len);
3783 cds_ssr_unprotect(__func__);
3784
3785 return ret;
3786}
3787#endif
3788
3789/*
3790 * define short names for the global vendor params
3791 * used by __wlan_hdd_cfg80211_monitor_rssi()
3792 */
3793#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
3794#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
3795#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
3796#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
3797#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
3798
3799/**
3800 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
3801 * @wiphy: Pointer to wireless phy
3802 * @wdev: Pointer to wireless device
3803 * @data: Pointer to data
3804 * @data_len: Data length
3805 *
3806 * Return: 0 on success, negative errno on failure
3807 */
3808static int
3809__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
3810 struct wireless_dev *wdev,
3811 const void *data,
3812 int data_len)
3813{
3814 struct net_device *dev = wdev->netdev;
3815 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3816 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3817 struct nlattr *tb[PARAM_MAX + 1];
3818 struct rssi_monitor_req req;
3819 CDF_STATUS status;
3820 int ret;
3821 uint32_t control;
3822 static const struct nla_policy policy[PARAM_MAX + 1] = {
3823 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
3824 [PARAM_CONTROL] = { .type = NLA_U32 },
3825 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
3826 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
3827 };
3828
3829 ENTER();
3830
3831 ret = wlan_hdd_validate_context(hdd_ctx);
3832 if (0 != ret) {
3833 hddLog(LOGE, FL("HDD context is not valid"));
3834 return -EINVAL;
3835 }
3836
3837 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3838 hddLog(LOGE, FL("Not in Connected state!"));
3839 return -ENOTSUPP;
3840 }
3841
3842 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
3843 hddLog(LOGE, FL("Invalid ATTR"));
3844 return -EINVAL;
3845 }
3846
3847 if (!tb[PARAM_REQUEST_ID]) {
3848 hddLog(LOGE, FL("attr request id failed"));
3849 return -EINVAL;
3850 }
3851
3852 if (!tb[PARAM_CONTROL]) {
3853 hddLog(LOGE, FL("attr control failed"));
3854 return -EINVAL;
3855 }
3856
3857 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3858 req.session_id = adapter->sessionId;
3859 control = nla_get_u32(tb[PARAM_CONTROL]);
3860
3861 if (control == QCA_WLAN_RSSI_MONITORING_START) {
3862 req.control = true;
3863 if (!tb[PARAM_MIN_RSSI]) {
3864 hddLog(LOGE, FL("attr min rssi failed"));
3865 return -EINVAL;
3866 }
3867
3868 if (!tb[PARAM_MAX_RSSI]) {
3869 hddLog(LOGE, FL("attr max rssi failed"));
3870 return -EINVAL;
3871 }
3872
3873 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
3874 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
3875
3876 if (!(req.min_rssi < req.max_rssi)) {
3877 hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"),
3878 req.min_rssi, req.max_rssi);
3879 return -EINVAL;
3880 }
3881 hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"),
3882 req.min_rssi, req.max_rssi);
3883
3884 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
3885 req.control = false;
3886 else {
3887 hddLog(LOGE, FL("Invalid control cmd: %d"), control);
3888 return -EINVAL;
3889 }
3890 hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"),
3891 req.request_id, req.session_id, req.control);
3892
3893 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
3894 if (!CDF_IS_STATUS_SUCCESS(status)) {
3895 hddLog(LOGE,
3896 FL("sme_set_rssi_monitoring failed(err=%d)"), status);
3897 return -EINVAL;
3898 }
3899
3900 return 0;
3901}
3902
3903/*
3904 * done with short names for the global vendor params
3905 * used by __wlan_hdd_cfg80211_monitor_rssi()
3906 */
3907#undef PARAM_MAX
3908#undef PARAM_CONTROL
3909#undef PARAM_REQUEST_ID
3910#undef PARAM_MAX_RSSI
3911#undef PARAM_MIN_RSSI
3912
3913/**
3914 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
3915 * @wiphy: wiphy structure pointer
3916 * @wdev: Wireless device structure pointer
3917 * @data: Pointer to the data received
3918 * @data_len: Length of @data
3919 *
3920 * Return: 0 on success; errno on failure
3921 */
3922static int
3923wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
3924 const void *data, int data_len)
3925{
3926 int ret;
3927
3928 cds_ssr_protect(__func__);
3929 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
3930 cds_ssr_unprotect(__func__);
3931
3932 return ret;
3933}
3934
3935/**
3936 * hdd_rssi_threshold_breached() - rssi breached NL event
3937 * @hddctx: HDD context
3938 * @data: rssi breached event data
3939 *
3940 * This function reads the rssi breached event %data and fill in the skb with
3941 * NL attributes and send up the NL event.
3942 *
3943 * Return: none
3944 */
3945void hdd_rssi_threshold_breached(void *hddctx,
3946 struct rssi_breach_event *data)
3947{
3948 hdd_context_t *hdd_ctx = hddctx;
3949 struct sk_buff *skb;
3950
3951 ENTER();
3952
3953 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
3954 hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"),
3955 data);
3956 return;
3957 }
3958
3959 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
3960 NULL,
3961 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
3962 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
3963 GFP_KERNEL);
3964
3965 if (!skb) {
3966 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
3967 return;
3968 }
3969
3970 hddLog(LOG1, "Req Id: %u Current rssi: %d",
3971 data->request_id, data->curr_rssi);
3972 hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR,
3973 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
3974
3975 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
3976 data->request_id) ||
3977 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
3978 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
3979 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
3980 data->curr_rssi)) {
3981 hddLog(LOGE, FL("nla put fail"));
3982 goto fail;
3983 }
3984
3985 cfg80211_vendor_event(skb, GFP_KERNEL);
3986 return;
3987
3988fail:
3989 kfree_skb(skb);
3990 return;
3991}
3992
3993/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
3994 * @wiphy: Pointer to wireless phy
3995 * @wdev: Pointer to wireless device
3996 * @data: Pointer to data
3997 * @data_len: Data length
3998 *
3999 * This function return the preferred frequency list generated by the policy
4000 * manager.
4001 *
4002 * Return: success or failure code
4003 */
4004static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4005 struct wireless_dev
4006 *wdev, const void *data,
4007 int data_len)
4008{
4009 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4010 int i, ret = 0;
4011 CDF_STATUS status;
4012 uint8_t pcl[MAX_NUM_CHAN];
4013 uint32_t pcl_len = 0;
4014 uint32_t freq_list[MAX_NUM_CHAN];
4015 enum cds_con_mode intf_mode;
4016 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4017 struct sk_buff *reply_skb;
4018
4019 ret = wlan_hdd_validate_context(hdd_ctx);
4020 if (ret)
4021 return -EINVAL;
4022
4023 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4024 data, data_len, NULL)) {
4025 hdd_err("Invalid ATTR");
4026 return -EINVAL;
4027 }
4028
4029 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4030 hdd_err("attr interface type failed");
4031 return -EINVAL;
4032 }
4033
4034 intf_mode = nla_get_u32(tb
4035 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4036
4037 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4038 hdd_err("Invalid interface type");
4039 return -EINVAL;
4040 }
4041
4042 hdd_debug("Userspace requested pref freq list");
4043
4044 status = cds_get_pcl(hdd_ctx, intf_mode, pcl, &pcl_len);
4045 if (status != CDF_STATUS_SUCCESS) {
4046 hdd_err("Get pcl failed");
4047 return -EINVAL;
4048 }
4049
4050 /* convert channel number to frequency */
4051 for (i = 0; i < pcl_len; i++) {
4052 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4053 freq_list[i] =
4054 ieee80211_channel_to_frequency(pcl[i],
4055 IEEE80211_BAND_2GHZ);
4056 else
4057 freq_list[i] =
4058 ieee80211_channel_to_frequency(pcl[i],
4059 IEEE80211_BAND_5GHZ);
4060 }
4061
4062 /* send the freq_list back to supplicant */
4063 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4064 sizeof(u32) *
4065 pcl_len +
4066 NLMSG_HDRLEN);
4067
4068 if (!reply_skb) {
4069 hdd_err("Allocate reply_skb failed");
4070 return -EINVAL;
4071 }
4072
4073 if (nla_put_u32(reply_skb,
4074 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4075 intf_mode) ||
4076 nla_put(reply_skb,
4077 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4078 sizeof(uint32_t) * pcl_len,
4079 freq_list)) {
4080 hdd_err("nla put fail");
4081 kfree_skb(reply_skb);
4082 return -EINVAL;
4083 }
4084
4085 return cfg80211_vendor_cmd_reply(reply_skb);
4086}
4087
4088/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4089 * @wiphy: Pointer to wireless phy
4090 * @wdev: Pointer to wireless device
4091 * @data: Pointer to data
4092 * @data_len: Data length
4093 *
4094 * This function return the preferred frequency list generated by the policy
4095 * manager.
4096 *
4097 * Return: success or failure code
4098 */
4099static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4100 struct wireless_dev
4101 *wdev, const void *data,
4102 int data_len)
4103{
4104 int ret = 0;
4105
4106 cds_ssr_protect(__func__);
4107 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
4108 data, data_len);
4109 cds_ssr_unprotect(__func__);
4110
4111 return ret;
4112}
4113
4114/**
4115 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4116 * @wiphy: Pointer to wireless phy
4117 * @wdev: Pointer to wireless device
4118 * @data: Pointer to data
4119 * @data_len: Data length
4120 *
4121 * Return: 0 on success, negative errno on failure
4122 */
4123static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4124 struct wireless_dev *wdev,
4125 const void *data,
4126 int data_len)
4127{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304128 struct net_device *ndev = wdev->netdev;
4129 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4131 int ret = 0;
4132 enum cds_con_mode intf_mode;
4133 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4134 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135
4136 ret = wlan_hdd_validate_context(hdd_ctx);
4137 if (ret)
4138 return ret;
4139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
4141 data, data_len, NULL)) {
4142 hdd_err("Invalid ATTR");
4143 return -EINVAL;
4144 }
4145
4146 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
4147 hdd_err("attr interface type failed");
4148 return -EINVAL;
4149 }
4150
4151 intf_mode = nla_get_u32(tb
4152 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
4153
4154 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4155 hdd_err("Invalid interface type");
4156 return -EINVAL;
4157 }
4158
4159 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
4160 hdd_err("attr probable freq failed");
4161 return -EINVAL;
4162 }
4163
4164 channel_hint = cds_freq_to_chan(nla_get_u32(tb
4165 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
4166
4167 /* check pcl table */
4168 if (!cds_allow_concurrency(hdd_ctx, intf_mode,
4169 channel_hint, HW_MODE_20_MHZ)) {
4170 hdd_err("Set channel hint failed due to concurrency check");
4171 return -EINVAL;
4172 }
4173
4174 if (hdd_ctx->config->policy_manager_enabled) {
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05304175 ret = cdf_reset_connection_update();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 if (!CDF_IS_STATUS_SUCCESS(ret))
4177 hdd_err("clearing event failed");
4178
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304179 ret = cds_current_connections_update(adapter->sessionId,
4180 channel_hint,
4181 CDS_UPDATE_REASON_SET_OPER_CHAN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004182 if (CDF_STATUS_E_FAILURE == ret) {
4183 /* return in the failure case */
4184 hdd_err("ERROR: connections update failed!!");
4185 return -EINVAL;
4186 }
4187
4188 if (CDF_STATUS_SUCCESS == ret) {
4189 /*
4190 * Success is the only case for which we expect hw mode
4191 * change to take place, hence we need to wait.
4192 * For any other return value it should be a pass
4193 * through
4194 */
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05304195 ret = cdf_wait_for_connection_update();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196 if (!CDF_IS_STATUS_SUCCESS(ret)) {
4197 hdd_err("ERROR: cdf wait for event failed!!");
4198 return -EINVAL;
4199 }
4200
4201 }
4202 }
4203
4204 return 0;
4205}
4206
4207/**
4208 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4209 * @wiphy: Pointer to wireless phy
4210 * @wdev: Pointer to wireless device
4211 * @data: Pointer to data
4212 * @data_len: Data length
4213 *
4214 * Return: 0 on success, negative errno on failure
4215 */
4216static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4217 struct wireless_dev *wdev,
4218 const void *data,
4219 int data_len)
4220{
4221 int ret = 0;
4222
4223 cds_ssr_protect(__func__);
4224 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
4225 data, data_len);
4226 cds_ssr_unprotect(__func__);
4227
4228 return ret;
4229}
4230
4231const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
4232 {
4233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
4235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4236 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4237 .doit = is_driver_dfs_capable
4238 },
4239
4240#ifdef WLAN_FEATURE_NAN
4241 {
4242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
4244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4245 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4246 .doit = wlan_hdd_cfg80211_nan_request
4247 },
4248#endif
4249
4250#ifdef WLAN_FEATURE_STATS_EXT
4251 {
4252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
4254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4255 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4256 .doit = wlan_hdd_cfg80211_stats_ext_request
4257 },
4258#endif
4259#ifdef FEATURE_WLAN_EXTSCAN
4260 {
4261 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4262 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
4263 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4264 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4265 .doit = wlan_hdd_cfg80211_extscan_start
4266 },
4267 {
4268 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4269 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
4270 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4271 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4272 .doit = wlan_hdd_cfg80211_extscan_stop
4273 },
4274 {
4275 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4276 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
4277 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4278 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
4279 },
4280 {
4281 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4282 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
4283 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4284 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4285 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
4286 },
4287 {
4288 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4289 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
4290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4291 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4292 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
4293 },
4294 {
4295 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4296 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
4297 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4298 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4299 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
4300 },
4301 {
4302 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4303 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
4304 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4305 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4306 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
4307 },
4308 {
4309 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4310 .info.subcmd =
4311 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
4312 .flags =
4313 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4314 WIPHY_VENDOR_CMD_NEED_RUNNING,
4315 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
4316 },
4317 {
4318 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4319 .info.subcmd =
4320 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
4321 .flags =
4322 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
4323 WIPHY_VENDOR_CMD_NEED_RUNNING,
4324 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
4325 },
4326 {
4327 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4328 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
4329 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4330 WIPHY_VENDOR_CMD_NEED_NETDEV |
4331 WIPHY_VENDOR_CMD_NEED_RUNNING,
4332 .doit = wlan_hdd_cfg80211_set_epno_list
4333 },
4334#endif /* FEATURE_WLAN_EXTSCAN */
4335
4336#ifdef WLAN_FEATURE_LINK_LAYER_STATS
4337 {
4338 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4339 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
4340 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4341 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4342 .doit = wlan_hdd_cfg80211_ll_stats_clear
4343 },
4344
4345 {
4346 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4347 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
4348 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4349 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4350 .doit = wlan_hdd_cfg80211_ll_stats_set
4351 },
4352
4353 {
4354 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4355 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
4356 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4357 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4358 .doit = wlan_hdd_cfg80211_ll_stats_get
4359 },
4360#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
4361#ifdef FEATURE_WLAN_TDLS
4362 {
4363 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4364 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
4365 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4366 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4367 .doit = wlan_hdd_cfg80211_exttdls_enable
4368 },
4369 {
4370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4371 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
4372 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4373 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
4374 .doit = wlan_hdd_cfg80211_exttdls_disable
4375 },
4376 {
4377 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4378 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
4379 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4380 .doit = wlan_hdd_cfg80211_exttdls_get_status
4381 },
4382#endif
4383 {
4384 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4385 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
4386 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4387 .doit = wlan_hdd_cfg80211_get_supported_features
4388 },
4389 {
4390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4391 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
4392 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4393 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
4394 },
4395 {
4396 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4397 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
4398 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
4399 .doit = cds_cfg80211_get_concurrency_matrix
4400 },
4401 {
4402 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4403 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
4404 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4405 WIPHY_VENDOR_CMD_NEED_NETDEV,
4406 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
4407 },
4408
4409 {
4410 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4411 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
4412 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4413 WIPHY_VENDOR_CMD_NEED_NETDEV |
4414 WIPHY_VENDOR_CMD_NEED_RUNNING,
4415 .doit = wlan_hdd_cfg80211_do_acs
4416 },
4417
4418 {
4419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
4421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4422 WIPHY_VENDOR_CMD_NEED_NETDEV,
4423 .doit = wlan_hdd_cfg80211_get_features
4424 },
4425#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4426 {
4427 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4428 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
4429 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4430 WIPHY_VENDOR_CMD_NEED_NETDEV |
4431 WIPHY_VENDOR_CMD_NEED_RUNNING,
4432 .doit = wlan_hdd_cfg80211_keymgmt_set_key
4433 },
4434#endif
4435#ifdef FEATURE_WLAN_EXTSCAN
4436 {
4437 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4438 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
4439 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4440 WIPHY_VENDOR_CMD_NEED_NETDEV |
4441 WIPHY_VENDOR_CMD_NEED_RUNNING,
4442 .doit = wlan_hdd_cfg80211_set_passpoint_list
4443 },
4444 {
4445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
4447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4448 WIPHY_VENDOR_CMD_NEED_NETDEV |
4449 WIPHY_VENDOR_CMD_NEED_RUNNING,
4450 .doit = wlan_hdd_cfg80211_reset_passpoint_list
4451 },
4452 {
4453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
4455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4456 WIPHY_VENDOR_CMD_NEED_NETDEV |
4457 WIPHY_VENDOR_CMD_NEED_RUNNING,
4458 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
4459 },
4460 {
4461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
4463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4464 WIPHY_VENDOR_CMD_NEED_NETDEV |
4465 WIPHY_VENDOR_CMD_NEED_RUNNING,
4466 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
4467 },
4468#endif /* FEATURE_WLAN_EXTSCAN */
4469 {
4470 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4471 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
4472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4473 WIPHY_VENDOR_CMD_NEED_NETDEV,
4474 .doit = wlan_hdd_cfg80211_get_wifi_info
4475 },
4476 {
4477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
4479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4480 WIPHY_VENDOR_CMD_NEED_NETDEV |
4481 WIPHY_VENDOR_CMD_NEED_RUNNING,
4482 .doit = wlan_hdd_cfg80211_wifi_configuration_set
4483 },
4484 {
4485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4486 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
4487 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4488 WIPHY_VENDOR_CMD_NEED_NETDEV,
4489 .doit = wlan_hdd_cfg80211_set_ext_roam_params
4490 },
4491 {
4492 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4493 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
4494 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4495 WIPHY_VENDOR_CMD_NEED_NETDEV,
4496 .doit = wlan_hdd_cfg80211_wifi_logger_start
4497 },
4498 {
4499 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4500 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
4501 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4502 WIPHY_VENDOR_CMD_NEED_NETDEV,
4503 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
4504 },
4505 {
4506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4507 .info.subcmd =
4508 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
4509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4510 WIPHY_VENDOR_CMD_NEED_NETDEV |
4511 WIPHY_VENDOR_CMD_NEED_RUNNING,
4512 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
4513 },
4514 {
4515 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4516 .info.subcmd =
4517 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
4518 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4519 WIPHY_VENDOR_CMD_NEED_NETDEV |
4520 WIPHY_VENDOR_CMD_NEED_RUNNING,
4521 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
4522 },
4523#ifdef FEATURE_WLAN_TDLS
4524 {
4525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
4527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4528 WIPHY_VENDOR_CMD_NEED_NETDEV |
4529 WIPHY_VENDOR_CMD_NEED_RUNNING,
4530 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
4531 },
4532#endif
4533#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4534 {
4535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4536 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
4537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4538 WIPHY_VENDOR_CMD_NEED_NETDEV |
4539 WIPHY_VENDOR_CMD_NEED_RUNNING,
4540 .doit = wlan_hdd_cfg80211_offloaded_packets
4541 },
4542#endif
4543 {
4544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4545 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
4546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4547 WIPHY_VENDOR_CMD_NEED_NETDEV |
4548 WIPHY_VENDOR_CMD_NEED_RUNNING,
4549 .doit = wlan_hdd_cfg80211_monitor_rssi
4550 },
4551 {
4552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
4554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4555 WIPHY_VENDOR_CMD_NEED_NETDEV |
4556 WIPHY_VENDOR_CMD_NEED_RUNNING,
4557 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
4558 },
4559#ifdef WLAN_FEATURE_MEMDUMP
4560 {
4561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
4563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4564 WIPHY_VENDOR_CMD_NEED_NETDEV |
4565 WIPHY_VENDOR_CMD_NEED_RUNNING,
4566 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
4567 },
4568#endif /* WLAN_FEATURE_MEMDUMP */
4569 {
4570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4571 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
4572 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4573 WIPHY_VENDOR_CMD_NEED_NETDEV |
4574 WIPHY_VENDOR_CMD_NEED_RUNNING,
4575 .doit = wlan_hdd_cfg80211_vendor_scan
4576 },
4577
4578 /* OCB commands */
4579 {
4580 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4581 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
4582 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4583 WIPHY_VENDOR_CMD_NEED_NETDEV |
4584 WIPHY_VENDOR_CMD_NEED_RUNNING,
4585 .doit = wlan_hdd_cfg80211_ocb_set_config
4586 },
4587 {
4588 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4589 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
4590 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4591 WIPHY_VENDOR_CMD_NEED_NETDEV |
4592 WIPHY_VENDOR_CMD_NEED_RUNNING,
4593 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
4594 },
4595 {
4596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4597 .info.subcmd =
4598 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
4599 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4600 WIPHY_VENDOR_CMD_NEED_NETDEV |
4601 WIPHY_VENDOR_CMD_NEED_RUNNING,
4602 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
4603 },
4604 {
4605 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4606 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
4607 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4608 WIPHY_VENDOR_CMD_NEED_NETDEV |
4609 WIPHY_VENDOR_CMD_NEED_RUNNING,
4610 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
4611 },
4612 {
4613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
4615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4616 WIPHY_VENDOR_CMD_NEED_NETDEV |
4617 WIPHY_VENDOR_CMD_NEED_RUNNING,
4618 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
4619 },
4620 {
4621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
4623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4624 WIPHY_VENDOR_CMD_NEED_NETDEV |
4625 WIPHY_VENDOR_CMD_NEED_RUNNING,
4626 .doit = wlan_hdd_cfg80211_dcc_get_stats
4627 },
4628 {
4629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
4631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4632 WIPHY_VENDOR_CMD_NEED_NETDEV |
4633 WIPHY_VENDOR_CMD_NEED_RUNNING,
4634 .doit = wlan_hdd_cfg80211_dcc_clear_stats
4635 },
4636 {
4637 .info.vendor_id = QCA_NL80211_VENDOR_ID,
4638 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
4639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
4640 WIPHY_VENDOR_CMD_NEED_NETDEV |
4641 WIPHY_VENDOR_CMD_NEED_RUNNING,
4642 .doit = wlan_hdd_cfg80211_dcc_update_ndl
4643 },
4644};
4645
4646/*
4647 * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc
4648 * This function is called by hdd_wlan_startup()
4649 * during initialization.
4650 * This function is used to allocate wiphy structure.
4651 */
4652struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size)
4653{
4654 struct wiphy *wiphy;
4655 ENTER();
4656
4657 /*
4658 * Create wiphy device
4659 */
4660 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
4661
4662 if (!wiphy) {
4663 /* Print error and jump into err label and free the memory */
4664 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: wiphy init failed",
4665 __func__);
4666 return NULL;
4667 }
4668
4669 return wiphy;
4670}
4671
4672/*
4673 * FUNCTION: wlan_hdd_cfg80211_update_band
4674 * This function is called from the supplicant through a
4675 * private ioctl to change the band value
4676 */
4677int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
4678{
4679 int i, j;
4680 CHANNEL_STATE channelEnabledState;
4681
4682 ENTER();
4683
4684 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
4685
4686 if (NULL == wiphy->bands[i]) {
4687 hddLog(CDF_TRACE_LEVEL_ERROR,
4688 "%s: wiphy->bands[i] is NULL, i = %d", __func__,
4689 i);
4690 continue;
4691 }
4692
4693 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
4694 struct ieee80211_supported_band *band = wiphy->bands[i];
4695
4696 channelEnabledState =
4697 cds_get_channel_state(band->channels[j].
4698 hw_value);
4699
4700 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
4701 /* 5G only */
4702#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
4703 /* Enable Social channels for P2P */
4704 if (WLAN_HDD_IS_SOCIAL_CHANNEL
4705 (band->channels[j].center_freq)
4706 && CHANNEL_STATE_ENABLE ==
4707 channelEnabledState)
4708 band->channels[j].flags &=
4709 ~IEEE80211_CHAN_DISABLED;
4710 else
4711#endif
4712 band->channels[j].flags |=
4713 IEEE80211_CHAN_DISABLED;
4714 continue;
4715 } else if (IEEE80211_BAND_5GHZ == i &&
4716 eCSR_BAND_24 == eBand) {
4717 /* 2G only */
4718 band->channels[j].flags |=
4719 IEEE80211_CHAN_DISABLED;
4720 continue;
4721 }
4722
4723 if (CHANNEL_STATE_DISABLE == channelEnabledState ||
4724 CHANNEL_STATE_INVALID == channelEnabledState) {
4725 band->channels[j].flags |=
4726 IEEE80211_CHAN_DISABLED;
4727 } else if (CHANNEL_STATE_DFS == channelEnabledState) {
4728 band->channels[j].flags &=
4729 ~IEEE80211_CHAN_DISABLED;
4730 band->channels[j].flags |= IEEE80211_CHAN_RADAR;
4731 } else {
4732 band->channels[j].flags &=
4733 ~(IEEE80211_CHAN_DISABLED |
4734 IEEE80211_CHAN_RADAR);
4735 }
4736 }
4737 }
4738 return 0;
4739}
4740
4741/*
4742 * FUNCTION: wlan_hdd_cfg80211_init
4743 * This function is called by hdd_wlan_startup()
4744 * during initialization.
4745 * This function is used to initialize and register wiphy structure.
4746 */
4747int wlan_hdd_cfg80211_init(struct device *dev,
4748 struct wiphy *wiphy, struct hdd_config *pCfg)
4749{
4750 int i, j;
4751 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
4752
4753 ENTER();
4754
4755 /* Now bind the underlying wlan device with wiphy */
4756 set_wiphy_dev(wiphy, dev);
4757
4758 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
4759
4760 /* This will disable updating of NL channels from passive to
4761 * active if a beacon is received on passive channel. */
4762#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
4763 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
4764#else
4765 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
4766#endif
4767
4768#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
4769 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
4770 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
4771 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
4772#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
4773 | WIPHY_FLAG_4ADDR_STATION
4774#endif
4775 | WIPHY_FLAG_OFFCHAN_TX;
4776
4777#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
4778 wiphy->regulatory_flags = REGULATORY_COUNTRY_IE_IGNORE;
4779#else
4780 wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE;
4781#endif
4782#endif
4783
4784#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4785 wiphy->wowlan = &wowlan_support_cfg80211_init;
4786#else
4787 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
4788 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
4789 wiphy->wowlan.pattern_min_len = 1;
4790 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
4791#endif
4792
4793#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
4794 if (pCfg->isFastTransitionEnabled
4795#ifdef FEATURE_WLAN_LFR
4796 || pCfg->isFastRoamIniFeatureEnabled
4797#endif
4798#ifdef FEATURE_WLAN_ESE
4799 || pCfg->isEseIniFeatureEnabled
4800#endif
4801 ) {
4802 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
4803 }
4804#endif
4805#ifdef FEATURE_WLAN_TDLS
4806 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
4807 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
4808#endif
4809
4810 wiphy->features |= NL80211_FEATURE_HT_IBSS;
4811
4812#ifdef FEATURE_WLAN_SCAN_PNO
4813 if (pCfg->configPNOScanSupport) {
4814 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4815 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
4816 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
4817 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
4818 }
4819#endif /*FEATURE_WLAN_SCAN_PNO */
4820
4821#if defined QCA_WIFI_FTM
4822 if (cds_get_conparam() != CDF_FTM_MODE) {
4823#endif
4824
4825 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
4826 driver can still register regulatory callback and
4827 it will get regulatory settings in wiphy->band[], but
4828 driver need to determine what to do with both
4829 regulatory settings */
4830
4831 wiphy->reg_notifier = hdd_reg_notifier;
4832
4833#if defined QCA_WIFI_FTM
4834}
4835#endif
4836
4837 wiphy->max_scan_ssids = MAX_SCAN_SSID;
4838
4839 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
4840
4841 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
4842
4843 /* Supports STATION & AD-HOC modes right now */
4844 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
4845 | BIT(NL80211_IFTYPE_ADHOC)
4846 | BIT(NL80211_IFTYPE_P2P_CLIENT)
4847 | BIT(NL80211_IFTYPE_P2P_GO)
4848 | BIT(NL80211_IFTYPE_AP);
4849
4850 if (pCfg->advertiseConcurrentOperation) {
4851#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
4852 if (pCfg->enableMCC) {
4853 int i;
4854 for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination);
4855 i++) {
4856 if (!pCfg->allowMCCGODiffBI)
4857 wlan_hdd_iface_combination[i].
4858 beacon_int_infra_match = true;
4859 }
4860 }
4861 wiphy->n_iface_combinations =
4862 ARRAY_SIZE(wlan_hdd_iface_combination);
4863 wiphy->iface_combinations = wlan_hdd_iface_combination;
4864#endif
4865 }
4866
4867 /* Before registering we need to update the ht capabilitied based
4868 * on ini values*/
4869 if (!pCfg->ShortGI20MhzEnable) {
4870 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
4871 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
4872 wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &=
4873 ~IEEE80211_HT_CAP_SGI_20;
4874 }
4875
4876 if (!pCfg->ShortGI40MhzEnable) {
4877 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
4878 }
4879
4880 if (!pCfg->nChannelBondingMode5GHz) {
4881 wlan_hdd_band_5_ghz.ht_cap.cap &=
4882 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
4883 }
4884
4885 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
4886 if (true == hdd_is_5g_supported(pHddCtx)) {
4887 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
4888 }
4889
4890 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
4891
4892 if (NULL == wiphy->bands[i]) {
4893 hddLog(CDF_TRACE_LEVEL_ERROR,
4894 "%s: wiphy->bands[i] is NULL, i = %d", __func__,
4895 i);
4896 continue;
4897 }
4898
4899 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
4900 struct ieee80211_supported_band *band = wiphy->bands[i];
4901
4902 if (IEEE80211_BAND_2GHZ == i &&
4903 eCSR_BAND_5G == pCfg->nBandCapability) {
4904 /* 5G only */
4905#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
4906 /* Enable social channels for P2P */
4907 if (WLAN_HDD_IS_SOCIAL_CHANNEL
4908 (band->channels[j].center_freq))
4909 band->channels[j].flags &=
4910 ~IEEE80211_CHAN_DISABLED;
4911 else
4912#endif
4913 band->channels[j].flags |=
4914 IEEE80211_CHAN_DISABLED;
4915 continue;
4916 } else if (IEEE80211_BAND_5GHZ == i &&
4917 eCSR_BAND_24 == pCfg->nBandCapability) {
4918 /* 2G only */
4919 band->channels[j].flags |=
4920 IEEE80211_CHAN_DISABLED;
4921 continue;
4922 }
4923 }
4924 }
4925 /*Initialise the supported cipher suite details */
4926 wiphy->cipher_suites = hdd_cipher_suites;
4927 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
4928
4929 /*signal strength in mBm (100*dBm) */
4930 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4931 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
4932
4933 if (cds_get_conparam() != CDF_FTM_MODE) {
4934 wiphy->n_vendor_commands =
4935 ARRAY_SIZE(hdd_wiphy_vendor_commands);
4936 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
4937
4938 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
4939 wiphy->n_vendor_events =
4940 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
4941 }
4942
4943#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 4, 0))
4944 if (pCfg->enableDFSMasterCap) {
4945 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
4946 }
4947#endif
4948
4949 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
4950
4951#ifdef QCA_HT_2040_COEX
4952 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
4953#endif
4954
4955 EXIT();
4956 return 0;
4957}
4958
4959/*
4960 * In this function, wiphy structure is updated after CDF
4961 * initialization. In wlan_hdd_cfg80211_init, only the
4962 * default values will be initialized. The final initialization
4963 * of all required members can be done here.
4964 */
4965void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
4966{
4967 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
4968}
4969
4970/* In this function we are registering wiphy. */
4971int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
4972{
4973 ENTER();
4974 /* Register our wiphy dev with cfg80211 */
4975 if (0 > wiphy_register(wiphy)) {
4976 /* print error */
4977 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: wiphy register failed",
4978 __func__);
4979 return -EIO;
4980 }
4981
4982 EXIT();
4983 return 0;
4984}
4985
4986/*
4987 HDD function to update wiphy capability based on target offload status.
4988
4989 wlan_hdd_cfg80211_init() does initialization of all wiphy related
4990 capability even before downloading firmware to the target. In discrete
4991 case, host will get know certain offload capability (say sched_scan
4992 caps) only after downloading firmware to the target and target boots up.
4993 This function is used to override setting done in wlan_hdd_cfg80211_init()
4994 based on target capability.
4995 */
4996void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
4997{
4998#ifdef FEATURE_WLAN_SCAN_PNO
4999 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
5000 struct hdd_config *pCfg = pHddCtx->config;
5001
5002 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
5003 * control comes here. Here just we need to clear it if firmware doesn't
5004 * have PNO support. */
5005 if (!pCfg->PnoOffload) {
5006 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
5007 wiphy->max_sched_scan_ssids = 0;
5008 wiphy->max_match_sets = 0;
5009 wiphy->max_sched_scan_ie_len = 0;
5010 }
5011#endif
5012}
5013
5014/* This function registers for all frame which supplicant is interested in */
5015void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
5016{
5017 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5018 /* Register for all P2P action, public action etc frames */
5019 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5020
5021 ENTER();
5022
5023 /* Right now we are registering these frame when driver is getting
5024 initialized. Once we will move to 2.6.37 kernel, in which we have
5025 frame register ops, we will move this code as a part of that */
5026 /* GAS Initial Request */
5027 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5028 (uint8_t *) GAS_INITIAL_REQ,
5029 GAS_INITIAL_REQ_SIZE);
5030
5031 /* GAS Initial Response */
5032 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5033 (uint8_t *) GAS_INITIAL_RSP,
5034 GAS_INITIAL_RSP_SIZE);
5035
5036 /* GAS Comeback Request */
5037 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5038 (uint8_t *) GAS_COMEBACK_REQ,
5039 GAS_COMEBACK_REQ_SIZE);
5040
5041 /* GAS Comeback Response */
5042 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5043 (uint8_t *) GAS_COMEBACK_RSP,
5044 GAS_COMEBACK_RSP_SIZE);
5045
5046 /* P2P Public Action */
5047 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5048 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5049 P2P_PUBLIC_ACTION_FRAME_SIZE);
5050
5051 /* P2P Action */
5052 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5053 (uint8_t *) P2P_ACTION_FRAME,
5054 P2P_ACTION_FRAME_SIZE);
5055
5056 /* WNM BSS Transition Request frame */
5057 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5058 (uint8_t *) WNM_BSS_ACTION_FRAME,
5059 WNM_BSS_ACTION_FRAME_SIZE);
5060
5061 /* WNM-Notification */
5062 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
5063 (uint8_t *) WNM_NOTIFICATION_FRAME,
5064 WNM_NOTIFICATION_FRAME_SIZE);
5065}
5066
5067void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
5068{
5069 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5070 /* Register for all P2P action, public action etc frames */
5071 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
5072
5073 ENTER();
5074
5075 /* Right now we are registering these frame when driver is getting
5076 initialized. Once we will move to 2.6.37 kernel, in which we have
5077 frame register ops, we will move this code as a part of that */
5078 /* GAS Initial Request */
5079
5080 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5081 (uint8_t *) GAS_INITIAL_REQ,
5082 GAS_INITIAL_REQ_SIZE);
5083
5084 /* GAS Initial Response */
5085 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5086 (uint8_t *) GAS_INITIAL_RSP,
5087 GAS_INITIAL_RSP_SIZE);
5088
5089 /* GAS Comeback Request */
5090 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5091 (uint8_t *) GAS_COMEBACK_REQ,
5092 GAS_COMEBACK_REQ_SIZE);
5093
5094 /* GAS Comeback Response */
5095 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5096 (uint8_t *) GAS_COMEBACK_RSP,
5097 GAS_COMEBACK_RSP_SIZE);
5098
5099 /* P2P Public Action */
5100 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5101 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
5102 P2P_PUBLIC_ACTION_FRAME_SIZE);
5103
5104 /* P2P Action */
5105 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
5106 (uint8_t *) P2P_ACTION_FRAME,
5107 P2P_ACTION_FRAME_SIZE);
5108
5109 /* WNM-Notification */
5110 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
5111 (uint8_t *) WNM_NOTIFICATION_FRAME,
5112 WNM_NOTIFICATION_FRAME_SIZE);
5113}
5114
5115#ifdef FEATURE_WLAN_WAPI
5116void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
5117 const uint8_t *mac_addr, const uint8_t *key,
5118 int key_Len)
5119{
5120 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5121 tCsrRoamSetKey setKey;
5122 bool isConnected = true;
5123 int status = 0;
5124 uint32_t roamId = 0xFF;
5125 uint8_t *pKeyPtr = NULL;
5126 int n = 0;
5127
5128 hddLog(LOG1, "Device_mode %s(%d)",
5129 hdd_device_mode_to_string(pAdapter->device_mode),
5130 pAdapter->device_mode);
5131
5132 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
5133 setKey.keyId = key_index; /* Store Key ID */
5134 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
5135 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
5136 setKey.paeRole = 0; /* the PAE role */
5137 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
5138 cdf_set_macaddr_broadcast(&setKey.peerMac);
5139 } else {
5140 cdf_mem_copy(setKey.peerMac.bytes, mac_addr, CDF_MAC_ADDR_SIZE);
5141 }
5142 setKey.keyLength = key_Len;
5143 pKeyPtr = setKey.Key;
5144 memcpy(pKeyPtr, key, key_Len);
5145
5146 hddLog(CDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x",
5147 __func__, key_Len);
5148 for (n = 0; n < key_Len; n++)
5149 hddLog(CDF_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
5150 __func__, n, setKey.Key[n]);
5151
5152 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
5153 if (isConnected) {
5154 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
5155 pAdapter->sessionId, &setKey, &roamId);
5156 }
5157 if (status != 0) {
5158 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
5159 "[%4d] sme_roam_set_key returned ERROR status= %d",
5160 __LINE__, status);
5161 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
5162 }
5163}
5164#endif /* FEATURE_WLAN_WAPI */
5165
5166uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
5167 uint8_t eid)
5168{
5169 int left = length;
5170 uint8_t *ptr = (uint8_t *)ies_ptr;
5171 uint8_t elem_id, elem_len;
5172
5173 while (left >= 2) {
5174 elem_id = ptr[0];
5175 elem_len = ptr[1];
5176 left -= 2;
5177 if (elem_len > left) {
5178 hddLog(CDF_TRACE_LEVEL_FATAL,
5179 FL("Invalid IEs eid = %d elem_len=%d left=%d"),
5180 eid, elem_len, left);
5181 return NULL;
5182 }
5183 if (elem_id == eid) {
5184 return ptr;
5185 }
5186
5187 left -= elem_len;
5188 ptr += (elem_len + 2);
5189 }
5190 return NULL;
5191}
5192
5193/*
5194 * FUNCTION: wlan_hdd_validate_operation_channel
5195 * called by wlan_hdd_cfg80211_start_bss() and
5196 * wlan_hdd_set_channel()
5197 * This function validates whether given channel is part of valid
5198 * channel list.
5199 */
5200CDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
5201 int channel)
5202{
5203
5204 uint32_t num_ch = 0;
5205 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
5206 u32 indx = 0;
5207 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
5208 uint8_t fValidChannel = false, count = 0;
5209 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
5210
5211 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
5212
5213 if (hdd_pConfig_ini->sapAllowAllChannel) {
5214 /* Validate the channel */
5215 for (count = RF_CHAN_1; count <= RF_CHAN_165; count++) {
5216 if (channel == rf_channels[count].channelNum) {
5217 fValidChannel = true;
5218 break;
5219 }
5220 }
5221 if (fValidChannel != true) {
5222 hddLog(CDF_TRACE_LEVEL_ERROR,
5223 "%s: Invalid Channel [%d]", __func__, channel);
5224 return CDF_STATUS_E_FAILURE;
5225 }
5226 } else {
5227 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
5228 valid_ch, &num_ch)) {
5229 hddLog(CDF_TRACE_LEVEL_ERROR,
5230 "%s: failed to get valid channel list",
5231 __func__);
5232 return CDF_STATUS_E_FAILURE;
5233 }
5234 for (indx = 0; indx < num_ch; indx++) {
5235 if (channel == valid_ch[indx]) {
5236 break;
5237 }
5238 }
5239
5240 if (indx >= num_ch) {
5241 hddLog(CDF_TRACE_LEVEL_ERROR,
5242 "%s: Invalid Channel [%d]", __func__, channel);
5243 return CDF_STATUS_E_FAILURE;
5244 }
5245 }
5246 return CDF_STATUS_SUCCESS;
5247
5248}
5249
5250#ifdef DHCP_SERVER_OFFLOAD
5251static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
5252{
5253 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
5254 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
5255 uint8_t numEntries = 0;
5256 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
5257 uint8_t num;
5258 uint32_t temp;
5259 pDhcpSrvInfo = cdf_mem_malloc(sizeof(*pDhcpSrvInfo));
5260 if (NULL == pDhcpSrvInfo) {
5261 hddLog(CDF_TRACE_LEVEL_ERROR,
5262 "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
5263 return;
5264 }
5265 cdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
5266 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
5267 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
5268 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
5269 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
5270 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
5271 if (numEntries != IPADDR_NUM_ENTRIES) {
5272 hddLog(CDF_TRACE_LEVEL_ERROR,
5273 "%s: incorrect IP address (%s) assigned for DHCP server!",
5274 __func__, pHddCtx->config->dhcpServerIP);
5275 goto end;
5276 }
5277 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
5278 hddLog(CDF_TRACE_LEVEL_ERROR,
5279 "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
5280 __func__, pHddCtx->config->dhcpServerIP);
5281 goto end;
5282 }
5283 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
5284 hddLog(CDF_TRACE_LEVEL_ERROR,
5285 "%s: invalid IP address (%s)! The last field must be less than 100!",
5286 __func__, pHddCtx->config->dhcpServerIP);
5287 goto end;
5288 }
5289 for (num = 0; num < numEntries; num++) {
5290 temp = srv_ip[num];
5291 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
5292 }
5293 if (CDF_STATUS_SUCCESS !=
5294 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
5295 hddLog(CDF_TRACE_LEVEL_ERROR,
5296 "%s: sme_setDHCPSrvOffload fail!", __func__);
5297 goto end;
5298 }
5299 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
5300 "%s: enable DHCP Server offload successfully!", __func__);
5301end:
5302 cdf_mem_free(pDhcpSrvInfo);
5303 return;
5304}
5305#endif /* DHCP_SERVER_OFFLOAD */
5306
5307static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
5308 struct net_device *dev,
5309 struct bss_parameters *params)
5310{
5311 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5312 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5313 int ret = 0;
5314 CDF_STATUS cdf_ret_status;
5315
5316 ENTER();
5317
5318 if (CDF_FTM_MODE == hdd_get_conparam()) {
5319 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5320 return -EINVAL;
5321 }
5322
5323 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
5324 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
5325 pAdapter->sessionId, params->ap_isolate));
5326 hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"),
5327 hdd_device_mode_to_string(pAdapter->device_mode),
5328 pAdapter->device_mode, params->ap_isolate);
5329
5330 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5331 ret = wlan_hdd_validate_context(pHddCtx);
5332 if (0 != ret) {
5333 hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid"));
5334 return ret;
5335 }
5336
5337 if (!(pAdapter->device_mode == WLAN_HDD_SOFTAP ||
5338 pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
5339 return -EOPNOTSUPP;
5340 }
5341
5342 /* ap_isolate == -1 means that in change bss, upper layer doesn't
5343 * want to update this parameter */
5344 if (-1 != params->ap_isolate) {
5345 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
5346 !!params->ap_isolate;
5347
5348 cdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
5349 pAdapter->sessionId,
5350 pAdapter->sessionCtx.
5351 ap.
5352 apDisableIntraBssFwd);
5353 if (!CDF_IS_STATUS_SUCCESS(cdf_ret_status)) {
5354 ret = -EINVAL;
5355 }
5356 }
5357
5358 EXIT();
5359 return ret;
5360}
5361
5362static int
5363wlan_hdd_change_iface_to_adhoc(struct net_device *ndev,
5364 tCsrRoamProfile *pRoamProfile,
5365 enum nl80211_iftype type)
5366{
5367 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5368 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5369 struct hdd_config *pConfig = pHddCtx->config;
5370 struct wireless_dev *wdev = ndev->ieee80211_ptr;
5371
5372 pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS;
5373 pRoamProfile->phyMode =
5374 hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode);
5375 pAdapter->device_mode = WLAN_HDD_IBSS;
5376 wdev->iftype = type;
5377
5378 return 0;
5379}
5380
5381static int wlan_hdd_change_iface_to_sta_mode(struct net_device *ndev,
5382 enum nl80211_iftype type)
5383{
5384 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5385 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5386 hdd_wext_state_t *wext;
5387 struct wireless_dev *wdev;
5388 CDF_STATUS status;
5389
5390 ENTER();
5391
5392 if (test_bit(ACS_IN_PROGRESS, &pHddCtx->g_event_flags)) {
5393 hddLog(LOG1, FL("ACS is in progress, don't change iface!"));
5394 return 0;
5395 }
5396
5397 wdev = ndev->ieee80211_ptr;
5398 hdd_stop_adapter(pHddCtx, pAdapter, true);
5399 hdd_deinit_adapter(pHddCtx, pAdapter, true);
5400 wdev->iftype = type;
5401 /*Check for sub-string p2p to confirm its a p2p interface */
5402 if (NULL != strnstr(ndev->name, "p2p", 3)) {
5403 pAdapter->device_mode =
5404 (type == NL80211_IFTYPE_STATION) ?
5405 WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT;
5406 } else {
5407 pAdapter->device_mode =
5408 (type == NL80211_IFTYPE_STATION) ?
5409 WLAN_HDD_INFRA_STATION : WLAN_HDD_P2P_CLIENT;
5410 }
5411
5412 /* set con_mode to STA only when no SAP concurrency mode */
5413 if (!(cds_get_concurrency_mode() & (CDF_SAP_MASK | CDF_P2P_GO_MASK)))
5414 hdd_set_conparam(0);
5415 memset(&pAdapter->sessionCtx, 0, sizeof(pAdapter->sessionCtx));
5416 hdd_set_station_ops(pAdapter->dev);
5417 status = hdd_init_station_mode(pAdapter);
5418 wext = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5419 wext->roamProfile.pAddIEScan = pAdapter->scan_info.scanAddIE.addIEdata;
5420 wext->roamProfile.nAddIEScanLength =
5421 pAdapter->scan_info.scanAddIE.length;
5422 EXIT();
5423 return status;
5424}
5425
5426static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
5427 struct net_device *dev,
5428 struct bss_parameters *params)
5429{
5430 int ret;
5431
5432 cds_ssr_protect(__func__);
5433 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
5434 cds_ssr_unprotect(__func__);
5435
5436 return ret;
5437}
5438
5439/* FUNCTION: wlan_hdd_change_country_code_cd
5440 * to wait for contry code completion
5441 */
5442void *wlan_hdd_change_country_code_cb(void *pAdapter)
5443{
5444 hdd_adapter_t *call_back_pAdapter = pAdapter;
5445 complete(&call_back_pAdapter->change_country_code);
5446 return NULL;
5447}
5448
5449/*
5450 * FUNCTION: __wlan_hdd_cfg80211_change_iface
5451 * This function is used to set the interface type (INFRASTRUCTURE/ADHOC)
5452 */
5453static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
5454 struct net_device *ndev,
5455 enum nl80211_iftype type,
5456 u32 *flags,
5457 struct vif_params *params)
5458{
5459 struct wireless_dev *wdev;
5460 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5461 hdd_context_t *pHddCtx;
5462 tCsrRoamProfile *pRoamProfile = NULL;
5463 eCsrRoamBssType LastBSSType;
5464 struct hdd_config *pConfig = NULL;
5465 eMib_dot11DesiredBssType connectedBssType;
5466 unsigned long rc;
5467 CDF_STATUS vstatus;
5468 int status;
5469
5470 ENTER();
5471
5472 if (CDF_FTM_MODE == hdd_get_conparam()) {
5473 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5474 return -EINVAL;
5475 }
5476
5477 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5478 status = wlan_hdd_validate_context(pHddCtx);
5479 if (0 != status) {
5480 hddLog(LOGE, FL("HDD context is not valid"));
5481 return status;
5482 }
5483
5484 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
5485 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
5486 pAdapter->sessionId, type));
5487
5488 hddLog(CDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"),
5489 pAdapter->device_mode, type);
5490
5491 if (!cds_allow_concurrency(pHddCtx,
5492 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
5493 0, HW_MODE_20_MHZ)) {
5494 hddLog(CDF_TRACE_LEVEL_DEBUG,
5495 FL("This concurrency combination is not allowed"));
5496 return -EINVAL;
5497 }
5498
5499 pConfig = pHddCtx->config;
5500 wdev = ndev->ieee80211_ptr;
5501
5502 /* Reset the current device mode bit mask */
5503 cds_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5504
5505 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
5506
5507 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
5508 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
5509 (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)) {
5510 hdd_wext_state_t *pWextState =
5511 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5512
5513 pRoamProfile = &pWextState->roamProfile;
5514 LastBSSType = pRoamProfile->BSSType;
5515
5516 switch (type) {
5517 case NL80211_IFTYPE_STATION:
5518 case NL80211_IFTYPE_P2P_CLIENT:
5519 vstatus = wlan_hdd_change_iface_to_sta_mode(ndev, type);
5520 if (vstatus != CDF_STATUS_SUCCESS)
5521 return -EINVAL;
5522
5523 hdd_register_tx_flow_control(pAdapter,
5524 hdd_tx_resume_timer_expired_handler,
5525 hdd_tx_resume_cb);
5526
5527 goto done;
5528
5529 case NL80211_IFTYPE_ADHOC:
5530 wlan_hdd_tdls_exit(pAdapter);
5531 hddLog(LOG1, FL("Setting interface Type to ADHOC"));
5532 wlan_hdd_change_iface_to_adhoc(ndev, pRoamProfile,
5533 type);
5534 break;
5535
5536 case NL80211_IFTYPE_AP:
5537 case NL80211_IFTYPE_P2P_GO:
5538 {
5539 hddLog(CDF_TRACE_LEVEL_INFO_HIGH,
5540 FL("Setting interface Type to %s"),
5541 (type ==
5542 NL80211_IFTYPE_AP) ? "SoftAP" :
5543 "P2pGo");
5544
5545 /* Cancel any remain on channel for GO mode */
5546 if (NL80211_IFTYPE_P2P_GO == type) {
5547 wlan_hdd_cancel_existing_remain_on_channel
5548 (pAdapter);
5549 }
5550
5551 if (NL80211_IFTYPE_AP == type) {
5552 /* As Loading WLAN Driver one interface being created for
5553 * p2p device address. This will take one HW STA and the
5554 * max number of clients that can connect to softAP will be
5555 * reduced by one. so while changing the interface type to
5556 * NL80211_IFTYPE_AP (SoftAP) remove p2p0 interface as it is
5557 * not required in SoftAP mode.
5558 */
5559
5560 /* Get P2P Adapter */
5561 hdd_adapter_t *pP2pAdapter = NULL;
5562 pP2pAdapter =
5563 hdd_get_adapter(pHddCtx,
5564 WLAN_HDD_P2P_DEVICE);
5565
5566 if (pP2pAdapter) {
5567 hdd_stop_adapter(pHddCtx,
5568 pP2pAdapter,
5569 true);
5570 hdd_deinit_adapter(pHddCtx,
5571 pP2pAdapter, true);
5572 hdd_close_adapter(pHddCtx,
5573 pP2pAdapter,
5574 true);
5575 }
5576 }
5577 hdd_stop_adapter(pHddCtx, pAdapter, true);
5578
5579 /* De-init the adapter */
5580 hdd_deinit_adapter(pHddCtx, pAdapter, true);
5581 memset(&pAdapter->sessionCtx, 0,
5582 sizeof(pAdapter->sessionCtx));
5583 pAdapter->device_mode =
5584 (type ==
5585 NL80211_IFTYPE_AP) ? WLAN_HDD_SOFTAP :
5586 WLAN_HDD_P2P_GO;
5587
5588 /*
5589 * Fw will take care incase of concurrency
5590 */
5591
5592 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode)
5593 && (pConfig->apRandomBssidEnabled)) {
5594 /* To meet Android requirements create a randomized
5595 MAC address of the form 02:1A:11:Fx:xx:xx */
5596 get_random_bytes(&ndev->dev_addr[3], 3);
5597 ndev->dev_addr[0] = 0x02;
5598 ndev->dev_addr[1] = 0x1A;
5599 ndev->dev_addr[2] = 0x11;
5600 ndev->dev_addr[3] |= 0xF0;
5601 memcpy(pAdapter->macAddressCurrent.
5602 bytes, ndev->dev_addr,
5603 CDF_MAC_ADDR_SIZE);
5604 pr_info("wlan: Generated HotSpot BSSID "
5605 MAC_ADDRESS_STR "\n",
5606 MAC_ADDR_ARRAY(ndev->dev_addr));
5607 }
5608
5609 hdd_set_ap_ops(pAdapter->dev);
5610
5611 vstatus = hdd_init_ap_mode(pAdapter);
5612 if (vstatus != CDF_STATUS_SUCCESS) {
5613 hddLog(LOGP,
5614 FL
5615 ("Error initializing the ap mode"));
5616 return -EINVAL;
5617 }
5618 hdd_set_conparam(1);
5619
5620 hdd_register_tx_flow_control(pAdapter,
5621 hdd_softap_tx_resume_timer_expired_handler,
5622 hdd_softap_tx_resume_cb);
5623
5624 /* Interface type changed update in wiphy structure */
5625 if (wdev) {
5626 wdev->iftype = type;
5627 } else {
5628 hddLog(LOGE,
5629 FL("Wireless dev is NULL"));
5630 return -EINVAL;
5631 }
5632 goto done;
5633 }
5634
5635 default:
5636 hddLog(LOGE, FL("Unsupported interface type (%d)"),
5637 type);
5638 return -EOPNOTSUPP;
5639 }
5640 } else if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
5641 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
5642 switch (type) {
5643 case NL80211_IFTYPE_STATION:
5644 case NL80211_IFTYPE_P2P_CLIENT:
5645 case NL80211_IFTYPE_ADHOC:
5646 status = wlan_hdd_change_iface_to_sta_mode(ndev, type);
5647 if (status != CDF_STATUS_SUCCESS)
5648 return status;
5649
5650 if ((NL80211_IFTYPE_P2P_CLIENT == type) ||
5651 (NL80211_IFTYPE_STATION == type)) {
5652
5653 hdd_register_tx_flow_control(pAdapter,
5654 hdd_tx_resume_timer_expired_handler,
5655 hdd_tx_resume_cb);
5656 }
5657 goto done;
5658
5659 case NL80211_IFTYPE_AP:
5660 case NL80211_IFTYPE_P2P_GO:
5661 wdev->iftype = type;
5662 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
5663 WLAN_HDD_SOFTAP : WLAN_HDD_P2P_GO;
5664
5665 hdd_register_tx_flow_control(pAdapter,
5666 hdd_softap_tx_resume_timer_expired_handler,
5667 hdd_softap_tx_resume_cb);
5668 goto done;
5669
5670 default:
5671 hddLog(LOGE, FL("Unsupported interface type(%d)"),
5672 type);
5673 return -EOPNOTSUPP;
5674 }
5675 } else {
5676 hddLog(LOGE, FL("Unsupported device mode(%d)"),
5677 pAdapter->device_mode);
5678 return -EOPNOTSUPP;
5679 }
5680
5681 if (LastBSSType != pRoamProfile->BSSType) {
5682 /* Interface type changed update in wiphy structure */
5683 wdev->iftype = type;
5684
5685 /* The BSS mode changed, We need to issue disconnect
5686 if connected or in IBSS disconnect state */
5687 if (hdd_conn_get_connected_bss_type
5688 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType)
5689 || (eCSR_BSS_TYPE_START_IBSS == LastBSSType)) {
5690 /* Need to issue a disconnect to CSR. */
5691 INIT_COMPLETION(pAdapter->disconnect_comp_var);
5692 if (CDF_STATUS_SUCCESS ==
5693 sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
5694 pAdapter->sessionId,
5695 eCSR_DISCONNECT_REASON_UNSPECIFIED)) {
5696 rc = wait_for_completion_timeout(&pAdapter->
5697 disconnect_comp_var,
5698 msecs_to_jiffies
5699 (WLAN_WAIT_TIME_DISCONNECT));
5700 if (!rc) {
5701 hddLog(LOGE,
5702 FL
5703 ("Wait on disconnect_comp_var failed"));
5704 }
5705 }
5706 }
5707 }
5708
5709done:
5710 /* Set bitmask based on updated value */
5711 cds_set_concurrency_mode(pHddCtx, pAdapter->device_mode);
5712
5713#ifdef WLAN_FEATURE_LPSS
5714 wlan_hdd_send_all_scan_intf_info(pHddCtx);
5715#endif
5716
5717 EXIT();
5718 return 0;
5719}
5720
5721/*
5722 * FUNCTION: wlan_hdd_cfg80211_change_iface
5723 * wrapper function to protect the actual implementation from SSR.
5724 */
5725static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
5726 struct net_device *ndev,
5727 enum nl80211_iftype type,
5728 u32 *flags,
5729 struct vif_params *params)
5730{
5731 int ret;
5732
5733 cds_ssr_protect(__func__);
5734 ret =
5735 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
5736 cds_ssr_unprotect(__func__);
5737
5738 return ret;
5739}
5740
5741#ifdef FEATURE_WLAN_TDLS
5742static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
5743 int index, uint8_t match)
5744{
5745 int i;
5746 for (i = 0; i < index; i++) {
5747 if (arr[i] == match)
5748 return true;
5749 }
5750 return false;
5751}
5752#endif
5753
5754/**
5755 * __wlan_hdd_change_station() - change station
5756 * @wiphy: Pointer to the wiphy structure
5757 * @dev: Pointer to the net device.
5758 * @mac: bssid
5759 * @params: Pointer to station parameters
5760 *
5761 * Return: 0 for success, error number on failure.
5762 */
5763#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
5764static int __wlan_hdd_change_station(struct wiphy *wiphy,
5765 struct net_device *dev,
5766 const uint8_t *mac,
5767 struct station_parameters *params)
5768#else
5769static int __wlan_hdd_change_station(struct wiphy *wiphy,
5770 struct net_device *dev,
5771 uint8_t *mac,
5772 struct station_parameters *params)
5773#endif
5774{
5775 CDF_STATUS status = CDF_STATUS_SUCCESS;
5776 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5777 hdd_context_t *pHddCtx;
5778 hdd_station_ctx_t *pHddStaCtx;
5779 struct cdf_mac_addr STAMacAddress;
5780#ifdef FEATURE_WLAN_TDLS
5781 tCsrStaParams StaParams = { 0 };
5782 uint8_t isBufSta = 0;
5783 uint8_t isOffChannelSupported = 0;
5784#endif
5785 int ret;
5786
5787 ENTER();
5788
5789 if (CDF_FTM_MODE == hdd_get_conparam()) {
5790 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5791 return -EINVAL;
5792 }
5793
5794 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
5795 TRACE_CODE_HDD_CHANGE_STATION,
5796 pAdapter->sessionId, params->listen_interval));
5797
5798 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5799 ret = wlan_hdd_validate_context(pHddCtx);
5800 if (0 != ret) {
5801 hddLog(CDF_TRACE_LEVEL_ERROR, FL("HDD context is not valid"));
5802 return ret;
5803 }
5804
5805 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5806
5807 cdf_mem_copy(STAMacAddress.bytes, mac, CDF_MAC_ADDR_SIZE);
5808
5809 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
5810 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
5811 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
5812 status =
5813 hdd_softap_change_sta_state(pAdapter,
5814 &STAMacAddress,
5815 ol_txrx_peer_state_auth);
5816
5817 if (status != CDF_STATUS_SUCCESS) {
5818 hddLog(CDF_TRACE_LEVEL_INFO,
5819 FL
5820 ("Not able to change TL state to AUTHENTICATED"));
5821 return -EINVAL;
5822 }
5823 }
5824 } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
5825 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
5826#ifdef FEATURE_WLAN_TDLS
5827 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
5828 StaParams.capability = params->capability;
5829 StaParams.uapsd_queues = params->uapsd_queues;
5830 StaParams.max_sp = params->max_sp;
5831
5832 /* Convert (first channel , number of channels) tuple to
5833 * the total list of channels. This goes with the assumption
5834 * that if the first channel is < 14, then the next channels
5835 * are an incremental of 1 else an incremental of 4 till the number
5836 * of channels.
5837 */
5838 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
5839 "%s: params->supported_channels_len: %d",
5840 __func__, params->supported_channels_len);
5841 if (0 != params->supported_channels_len) {
5842 int i = 0, j = 0, k = 0, no_of_channels = 0;
5843 int num_unique_channels;
5844 int next;
5845 for (i = 0;
5846 i < params->supported_channels_len
5847 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
5848 int wifi_chan_index;
5849 if (!wlan_hdd_is_duplicate_channel
5850 (StaParams.supported_channels, j,
5851 params->supported_channels[i])) {
5852 StaParams.
5853 supported_channels[j] =
5854 params->
5855 supported_channels[i];
5856 } else {
5857 continue;
5858 }
5859 wifi_chan_index =
5860 ((StaParams.supported_channels[j] <=
5861 HDD_CHANNEL_14) ? 1 : 4);
5862 no_of_channels =
5863 params->supported_channels[i + 1];
5864
5865 CDF_TRACE(CDF_MODULE_ID_HDD,
5866 CDF_TRACE_LEVEL_INFO,
5867 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d",
5868 __func__, i, j, k, j,
5869 StaParams.
5870 supported_channels[j],
5871 wifi_chan_index,
5872 no_of_channels);
5873 for (k = 1; k <= no_of_channels &&
5874 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
5875 k++) {
5876 next =
5877 StaParams.
5878 supported_channels[j] +
5879 wifi_chan_index;
5880 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
5881 StaParams.
5882 supported_channels[j
5883 +
5884 1]
5885 = next;
5886 } else {
5887 continue;
5888 }
5889 CDF_TRACE(CDF_MODULE_ID_HDD,
5890 CDF_TRACE_LEVEL_INFO,
5891 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d",
5892 __func__, i, j, k,
5893 j + 1,
5894 StaParams.
5895 supported_channels[j +
5896 1]);
5897 j += 1;
5898 }
5899 }
5900 num_unique_channels = j + 1;
5901 CDF_TRACE(CDF_MODULE_ID_HDD,
5902 CDF_TRACE_LEVEL_INFO,
5903 "%s: Unique Channel List", __func__);
5904 for (i = 0; i < num_unique_channels; i++) {
5905 CDF_TRACE(CDF_MODULE_ID_HDD,
5906 CDF_TRACE_LEVEL_INFO,
5907 "%s: StaParams.supported_channels[%d]: %d,",
5908 __func__, i,
5909 StaParams.
5910 supported_channels[i]);
5911 }
5912 if (MAX_CHANNEL < num_unique_channels)
5913 num_unique_channels = MAX_CHANNEL;
5914 StaParams.supported_channels_len =
5915 num_unique_channels;
5916 CDF_TRACE(CDF_MODULE_ID_HDD,
5917 CDF_TRACE_LEVEL_INFO,
5918 "%s: After removing duplcates StaParams.supported_channels_len: %d",
5919 __func__,
5920 StaParams.supported_channels_len);
5921 }
5922 cdf_mem_copy(StaParams.supported_oper_classes,
5923 params->supported_oper_classes,
5924 params->supported_oper_classes_len);
5925 StaParams.supported_oper_classes_len =
5926 params->supported_oper_classes_len;
5927
5928 if (0 != params->ext_capab_len)
5929 cdf_mem_copy(StaParams.extn_capability,
5930 params->ext_capab,
5931 sizeof(StaParams.extn_capability));
5932
5933 if (NULL != params->ht_capa) {
5934 StaParams.htcap_present = 1;
5935 cdf_mem_copy(&StaParams.HTCap, params->ht_capa,
5936 sizeof(tSirHTCap));
5937 }
5938
5939 StaParams.supported_rates_len =
5940 params->supported_rates_len;
5941
5942 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
5943 * The supported_rates array , for all the structures propogating till Add Sta
5944 * to the firmware has to be modified , if the supplicant (ieee80211) is
5945 * modified to send more rates.
5946 */
5947
5948 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
5949 */
5950 if (StaParams.supported_rates_len >
5951 SIR_MAC_MAX_SUPP_RATES)
5952 StaParams.supported_rates_len =
5953 SIR_MAC_MAX_SUPP_RATES;
5954
5955 if (0 != StaParams.supported_rates_len) {
5956 int i = 0;
5957 cdf_mem_copy(StaParams.supported_rates,
5958 params->supported_rates,
5959 StaParams.supported_rates_len);
5960 CDF_TRACE(CDF_MODULE_ID_HDD,
5961 CDF_TRACE_LEVEL_INFO,
5962 "Supported Rates with Length %d",
5963 StaParams.supported_rates_len);
5964 for (i = 0; i < StaParams.supported_rates_len;
5965 i++)
5966 CDF_TRACE(CDF_MODULE_ID_HDD,
5967 CDF_TRACE_LEVEL_INFO,
5968 "[%d]: %0x", i,
5969 StaParams.supported_rates[i]);
5970 }
5971
5972 if (NULL != params->vht_capa) {
5973 StaParams.vhtcap_present = 1;
5974 cdf_mem_copy(&StaParams.VHTCap,
5975 params->vht_capa,
5976 sizeof(tSirVHTCap));
5977 }
5978
5979 if (0 != params->ext_capab_len) {
5980 /*Define A Macro : TODO Sunil */
5981 if ((1 << 4) & StaParams.extn_capability[3]) {
5982 isBufSta = 1;
5983 }
5984 /* TDLS Channel Switching Support */
5985 if ((1 << 6) & StaParams.extn_capability[3]) {
5986 isOffChannelSupported = 1;
5987 }
5988 }
5989
5990 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
5991 &StaParams,
5992 isBufSta,
5993 isOffChannelSupported);
5994 if (CDF_STATUS_SUCCESS != status) {
5995 hddLog(CDF_TRACE_LEVEL_ERROR,
5996 FL
5997 ("wlan_hdd_tdls_set_peer_caps failed!"));
5998 return -EINVAL;
5999 }
6000
6001 status =
6002 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
6003 &StaParams);
6004 if (CDF_STATUS_SUCCESS != status) {
6005 hddLog(CDF_TRACE_LEVEL_ERROR,
6006 FL("wlan_hdd_tdls_add_station failed!"));
6007 return -EINVAL;
6008 }
6009 }
6010#endif
6011 }
6012 EXIT();
6013 return ret;
6014}
6015
6016/**
6017 * wlan_hdd_change_station() - cfg80211 change station handler function
6018 * @wiphy: Pointer to the wiphy structure
6019 * @dev: Pointer to the net device.
6020 * @mac: bssid
6021 * @params: Pointer to station parameters
6022 *
6023 * This is the cfg80211 change station handler function which invokes
6024 * the internal function @__wlan_hdd_change_station with
6025 * SSR protection.
6026 *
6027 * Return: 0 for success, error number on failure.
6028 */
6029#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
6030static int wlan_hdd_change_station(struct wiphy *wiphy,
6031 struct net_device *dev,
6032 const u8 *mac,
6033 struct station_parameters *params)
6034#else
6035static int wlan_hdd_change_station(struct wiphy *wiphy,
6036 struct net_device *dev,
6037 u8 *mac,
6038 struct station_parameters *params)
6039#endif
6040{
6041 int ret;
6042
6043 cds_ssr_protect(__func__);
6044 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
6045 cds_ssr_unprotect(__func__);
6046
6047 return ret;
6048}
6049
6050/*
6051 * FUNCTION: __wlan_hdd_cfg80211_add_key
6052 * This function is used to initialize the key information
6053 */
6054static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6055 struct net_device *ndev,
6056 u8 key_index, bool pairwise,
6057 const u8 *mac_addr,
6058 struct key_params *params)
6059{
6060 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6061 tCsrRoamSetKey setKey;
6062 int status;
6063 uint32_t roamId = 0xFF;
6064#ifndef WLAN_FEATURE_MBSSID
6065 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context;
6066#endif
6067 hdd_hostapd_state_t *pHostapdState;
6068 CDF_STATUS cdf_ret_status;
6069 hdd_context_t *pHddCtx;
6070 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6071
6072 ENTER();
6073
6074 if (CDF_FTM_MODE == hdd_get_conparam()) {
6075 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6076 return -EINVAL;
6077 }
6078
6079 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
6080 TRACE_CODE_HDD_CFG80211_ADD_KEY,
6081 pAdapter->sessionId, params->key_len));
6082 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6083 status = wlan_hdd_validate_context(pHddCtx);
6084
6085 if (0 != status) {
6086 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
6087 "%s: HDD context is not valid", __func__);
6088 return status;
6089 }
6090
6091 hddLog(LOG1, FL("Device_mode %s(%d)"),
6092 hdd_device_mode_to_string(pAdapter->device_mode),
6093 pAdapter->device_mode);
6094
6095 if (CSR_MAX_NUM_KEY <= key_index) {
6096 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d",
6097 __func__, key_index);
6098
6099 return -EINVAL;
6100 }
6101
6102 if (CSR_MAX_KEY_LEN < params->key_len) {
6103 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d",
6104 __func__, params->key_len);
6105
6106 return -EINVAL;
6107 }
6108
6109 hddLog(CDF_TRACE_LEVEL_INFO,
6110 "%s: called with key index = %d & key length %d",
6111 __func__, key_index, params->key_len);
6112
6113 /*extract key idx, key len and key */
6114 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
6115 setKey.keyId = key_index;
6116 setKey.keyLength = params->key_len;
6117 cdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
6118
6119 switch (params->cipher) {
6120 case WLAN_CIPHER_SUITE_WEP40:
6121 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
6122 break;
6123
6124 case WLAN_CIPHER_SUITE_WEP104:
6125 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
6126 break;
6127
6128 case WLAN_CIPHER_SUITE_TKIP:
6129 {
6130 u8 *pKey = &setKey.Key[0];
6131 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
6132
6133 cdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
6134
6135 /*Supplicant sends the 32bytes key in this order
6136
6137 |--------------|----------|----------|
6138 | Tk1 |TX-MIC | RX Mic |
6139 |||--------------|----------|----------|
6140 <---16bytes---><--8bytes--><--8bytes-->
6141
6142 */
6143 /*Sme expects the 32 bytes key to be in the below order
6144
6145 |--------------|----------|----------|
6146 | Tk1 |RX-MIC | TX Mic |
6147 |||--------------|----------|----------|
6148 <---16bytes---><--8bytes--><--8bytes-->
6149 */
6150 /* Copy the Temporal Key 1 (TK1) */
6151 cdf_mem_copy(pKey, params->key, 16);
6152
6153 /*Copy the rx mic first */
6154 cdf_mem_copy(&pKey[16], &params->key[24], 8);
6155
6156 /*Copy the tx mic */
6157 cdf_mem_copy(&pKey[24], &params->key[16], 8);
6158
6159 break;
6160 }
6161
6162 case WLAN_CIPHER_SUITE_CCMP:
6163 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
6164 break;
6165
6166#ifdef FEATURE_WLAN_WAPI
6167 case WLAN_CIPHER_SUITE_SMS4:
6168 {
6169 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
6170 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
6171 mac_addr, params->key,
6172 params->key_len);
6173 return 0;
6174 }
6175#endif
6176
6177#ifdef FEATURE_WLAN_ESE
6178 case WLAN_CIPHER_SUITE_KRK:
6179 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
6180 break;
6181#ifdef WLAN_FEATURE_ROAM_OFFLOAD
6182 case WLAN_CIPHER_SUITE_BTK:
6183 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
6184 break;
6185#endif
6186#endif
6187
6188#ifdef WLAN_FEATURE_11W
6189 case WLAN_CIPHER_SUITE_AES_CMAC:
6190 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
6191 break;
6192#endif
6193
6194 default:
6195 hddLog(CDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
6196 __func__, params->cipher);
6197 return -EOPNOTSUPP;
6198 }
6199
6200 hddLog(CDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
6201 __func__, setKey.encType);
6202
6203 if (!pairwise) {
6204 /* set group key */
6205 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
6206 "%s- %d: setting Broadcast key", __func__, __LINE__);
6207 setKey.keyDirection = eSIR_RX_ONLY;
6208 cdf_set_macaddr_broadcast(&setKey.peerMac);
6209 } else {
6210 /* set pairwise key */
6211 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO,
6212 "%s- %d: setting pairwise key", __func__, __LINE__);
6213 setKey.keyDirection = eSIR_TX_RX;
6214 cdf_mem_copy(setKey.peerMac.bytes, mac_addr, CDF_MAC_ADDR_SIZE);
6215 }
6216 if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise) {
6217 /* if a key is already installed, block all subsequent ones */
6218 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
6219 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6220 "%s: IBSS key installed already", __func__);
6221 return 0;
6222 }
6223
6224 setKey.keyDirection = eSIR_TX_RX;
6225 /*Set the group key */
6226 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6227 pAdapter->sessionId, &setKey, &roamId);
6228
6229 if (0 != status) {
6230 hddLog(CDF_TRACE_LEVEL_ERROR,
6231 "%s: sme_roam_set_key failed, returned %d",
6232 __func__, status);
6233 return -EINVAL;
6234 }
6235 /*Save the keys here and call sme_roam_set_key for setting
6236 the PTK after peer joins the IBSS network */
6237 cdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
6238 &setKey, sizeof(tCsrRoamSetKey));
6239
6240 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
6241 return status;
6242 }
6243 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) ||
6244 (pAdapter->device_mode == WLAN_HDD_P2P_GO)) {
6245 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6246 if (pHostapdState->bssState == BSS_START) {
6247#ifdef WLAN_FEATURE_MBSSID
6248 status =
6249 wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR
6250 (pAdapter), &setKey);
6251#else
6252 status = wlansap_set_key_sta(p_cds_context, &setKey);
6253#endif
6254 if (status != CDF_STATUS_SUCCESS) {
6255 CDF_TRACE(CDF_MODULE_ID_HDD,
6256 CDF_TRACE_LEVEL_ERROR,
6257 "[%4d] wlansap_set_key_sta returned ERROR status= %d",
6258 __LINE__, status);
6259 }
6260 }
6261
6262 /* Save the key in ap ctx for use on START_BASS and restart */
6263 if (pairwise ||
6264 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
6265 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
6266 cdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
6267 sizeof(tCsrRoamSetKey));
6268 else
6269 cdf_mem_copy(&ap_ctx->groupKey, &setKey,
6270 sizeof(tCsrRoamSetKey));
6271
6272 } else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6273 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
6274 hdd_wext_state_t *pWextState =
6275 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6276 hdd_station_ctx_t *pHddStaCtx =
6277 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6278
6279 if (!pairwise) {
6280 /* set group key */
6281 if (pHddStaCtx->roam_info.deferKeyComplete) {
6282 CDF_TRACE(CDF_MODULE_ID_HDD,
6283 CDF_TRACE_LEVEL_INFO,
6284 "%s- %d: Perform Set key Complete",
6285 __func__, __LINE__);
6286 hdd_perform_roam_set_key_complete(pAdapter);
6287 }
6288 }
6289
6290 pWextState->roamProfile.Keys.KeyLength[key_index] =
6291 (u8) params->key_len;
6292
6293 pWextState->roamProfile.Keys.defaultIndex = key_index;
6294
6295 cdf_mem_copy(&pWextState->roamProfile.Keys.
6296 KeyMaterial[key_index][0], params->key,
6297 params->key_len);
6298
6299 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6300
6301 hddLog(LOG2,
6302 FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"),
6303 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6304 setKey.keyDirection);
6305
6306#ifdef WLAN_FEATURE_VOWIFI_11R
6307 /* The supplicant may attempt to set the PTK once pre-authentication
6308 is done. Save the key in the UMAC and include it in the ADD BSS
6309 request */
6310 cdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6311 pAdapter->sessionId, &setKey);
6312 if (cdf_ret_status == CDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
6313 hddLog(CDF_TRACE_LEVEL_INFO_MED,
6314 "%s: Update PreAuth Key success", __func__);
6315 return 0;
6316 } else if (cdf_ret_status == CDF_STATUS_FT_PREAUTH_KEY_FAILED) {
6317 hddLog(CDF_TRACE_LEVEL_ERROR,
6318 "%s: Update PreAuth Key failed", __func__);
6319 return -EINVAL;
6320 }
6321#endif /* WLAN_FEATURE_VOWIFI_11R */
6322
6323 /* issue set key request to SME */
6324 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6325 pAdapter->sessionId, &setKey, &roamId);
6326
6327 if (0 != status) {
6328 hddLog(CDF_TRACE_LEVEL_ERROR,
6329 "%s: sme_roam_set_key failed, returned %d",
6330 __func__, status);
6331 pHddStaCtx->roam_info.roamingState =
6332 HDD_ROAM_STATE_NONE;
6333 return -EINVAL;
6334 }
6335
6336 /* in case of IBSS as there was no information available about WEP keys during
6337 * IBSS join, group key intialized with NULL key, so re-initialize group key
6338 * with correct value*/
6339 if ((eCSR_BSS_TYPE_START_IBSS ==
6340 pWextState->roamProfile.BSSType)
6341 &&
6342 !((IW_AUTH_KEY_MGMT_802_1X ==
6343 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
6344 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
6345 pHddStaCtx->conn_info.authType)
6346 )
6347 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
6348 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
6349 )
6350 ) {
6351 setKey.keyDirection = eSIR_RX_ONLY;
6352 cdf_set_macaddr_broadcast(&setKey.peerMac);
6353
6354 hddLog(LOG2,
6355 FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"),
6356 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
6357 setKey.keyDirection);
6358
6359 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6360 pAdapter->sessionId, &setKey,
6361 &roamId);
6362
6363 if (0 != status) {
6364 hddLog(CDF_TRACE_LEVEL_ERROR,
6365 "%s: sme_roam_set_key failed for group key (IBSS), returned %d",
6366 __func__, status);
6367 pHddStaCtx->roam_info.roamingState =
6368 HDD_ROAM_STATE_NONE;
6369 return -EINVAL;
6370 }
6371 }
6372 }
6373
6374 return 0;
6375}
6376
6377static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
6378 struct net_device *ndev,
6379 u8 key_index, bool pairwise,
6380 const u8 *mac_addr,
6381 struct key_params *params)
6382{
6383 int ret;
6384 cds_ssr_protect(__func__);
6385 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
6386 mac_addr, params);
6387 cds_ssr_unprotect(__func__);
6388
6389 return ret;
6390}
6391
6392/*
6393 * FUNCTION: __wlan_hdd_cfg80211_get_key
6394 * This function is used to get the key information
6395 */
6396static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
6397 struct net_device *ndev,
6398 u8 key_index, bool pairwise,
6399 const u8 *mac_addr, void *cookie,
6400 void (*callback)(void *cookie,
6401 struct key_params *)
6402 )
6403{
6404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6405 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6406 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
6407 struct key_params params;
6408
6409 ENTER();
6410
6411 if (CDF_FTM_MODE == hdd_get_conparam()) {
6412 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6413 return -EINVAL;
6414 }
6415
6416 hddLog(LOG1, FL("Device_mode %s(%d)"),
6417 hdd_device_mode_to_string(pAdapter->device_mode),
6418 pAdapter->device_mode);
6419
6420 memset(&params, 0, sizeof(params));
6421
6422 if (CSR_MAX_NUM_KEY <= key_index) {
6423 hddLog(CDF_TRACE_LEVEL_ERROR, FL("invalid key index %d"),
6424 key_index);
6425 return -EINVAL;
6426 }
6427
6428 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
6429 case eCSR_ENCRYPT_TYPE_NONE:
6430 params.cipher = IW_AUTH_CIPHER_NONE;
6431 break;
6432
6433 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
6434 case eCSR_ENCRYPT_TYPE_WEP40:
6435 params.cipher = WLAN_CIPHER_SUITE_WEP40;
6436 break;
6437
6438 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
6439 case eCSR_ENCRYPT_TYPE_WEP104:
6440 params.cipher = WLAN_CIPHER_SUITE_WEP104;
6441 break;
6442
6443 case eCSR_ENCRYPT_TYPE_TKIP:
6444 params.cipher = WLAN_CIPHER_SUITE_TKIP;
6445 break;
6446
6447 case eCSR_ENCRYPT_TYPE_AES:
6448 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6449 break;
6450
6451 default:
6452 params.cipher = IW_AUTH_CIPHER_NONE;
6453 break;
6454 }
6455
6456 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
6457 TRACE_CODE_HDD_CFG80211_GET_KEY,
6458 pAdapter->sessionId, params.cipher));
6459
6460 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
6461 params.seq_len = 0;
6462 params.seq = NULL;
6463 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
6464 callback(cookie, &params);
6465
6466 EXIT();
6467 return 0;
6468}
6469
6470static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
6471 struct net_device *ndev,
6472 u8 key_index, bool pairwise,
6473 const u8 *mac_addr, void *cookie,
6474 void (*callback)(void *cookie,
6475 struct key_params *)
6476 )
6477{
6478 int ret;
6479
6480 cds_ssr_protect(__func__);
6481 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
6482 mac_addr, cookie, callback);
6483 cds_ssr_unprotect(__func__);
6484
6485 return ret;
6486}
6487
6488/**
6489 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
6490 * @wiphy: wiphy interface context
6491 * @ndev: pointer to net device
6492 * @key_index: Key index used in 802.11 frames
6493 * @unicast: true if it is unicast key
6494 * @multicast: true if it is multicast key
6495 *
6496 * This function is required for cfg80211_ops API.
6497 * It is used to delete the key information
6498 * Underlying hardware implementation does not have API to delete the
6499 * encryption key. It is automatically deleted when the peer is
6500 * removed. Hence this function currently does nothing.
6501 * Future implementation may interprete delete key operation to
6502 * replacing the key with a random junk value, effectively making it
6503 * useless.
6504 *
6505 * Return: status code, always 0.
6506 */
6507
6508static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
6509 struct net_device *ndev,
6510 u8 key_index,
6511 bool pairwise, const u8 *mac_addr)
6512{
6513 EXIT();
6514 return 0;
6515}
6516
6517/**
6518 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
6519 * @wiphy: Pointer to wiphy structure.
6520 * @dev: Pointer to net_device structure.
6521 * @key_index: key index
6522 * @pairwise: pairwise
6523 * @mac_addr: mac address
6524 *
6525 * This is the cfg80211 delete key handler function which invokes
6526 * the internal function @__wlan_hdd_cfg80211_del_key with
6527 * SSR protection.
6528 *
6529 * Return: 0 for success, error number on failure.
6530 */
6531static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
6532 struct net_device *dev,
6533 u8 key_index,
6534 bool pairwise, const u8 *mac_addr)
6535{
6536 int ret;
6537
6538 cds_ssr_protect(__func__);
6539 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
6540 pairwise, mac_addr);
6541 cds_ssr_unprotect(__func__);
6542
6543 return ret;
6544}
6545
6546/*
6547 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
6548 * This function is used to set the default tx key index
6549 */
6550static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
6551 struct net_device *ndev,
6552 u8 key_index,
6553 bool unicast, bool multicast)
6554{
6555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6556 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6557 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6558 hdd_context_t *pHddCtx;
6559 int status;
6560
6561 ENTER();
6562
6563 if (CDF_FTM_MODE == hdd_get_conparam()) {
6564 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6565 return -EINVAL;
6566 }
6567
6568 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
6569 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
6570 pAdapter->sessionId, key_index));
6571
6572 hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"),
6573 hdd_device_mode_to_string(pAdapter->device_mode),
6574 pAdapter->device_mode, key_index);
6575
6576 if (CSR_MAX_NUM_KEY <= key_index) {
6577 hddLog(LOGE, FL("Invalid key index %d"), key_index);
6578 return -EINVAL;
6579 }
6580
6581 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6582 status = wlan_hdd_validate_context(pHddCtx);
6583
6584 if (0 != status) {
6585 hddLog(LOGE, FL("HDD context is not valid"));
6586 return status;
6587 }
6588
6589 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
6590 (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) {
6591 if ((eCSR_ENCRYPT_TYPE_TKIP !=
6592 pHddStaCtx->conn_info.ucEncryptionType) &&
6593 (eCSR_ENCRYPT_TYPE_AES !=
6594 pHddStaCtx->conn_info.ucEncryptionType)) {
6595 /* If default key index is not same as previous one,
6596 * then update the default key index */
6597
6598 tCsrRoamSetKey setKey;
6599 uint32_t roamId = 0xFF;
6600 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
6601
6602 hddLog(LOG2, FL("Default tx key index %d"), key_index);
6603
6604 Keys->defaultIndex = (u8) key_index;
6605 cdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
6606 setKey.keyId = key_index;
6607 setKey.keyLength = Keys->KeyLength[key_index];
6608
6609 cdf_mem_copy(&setKey.Key[0],
6610 &Keys->KeyMaterial[key_index][0],
6611 Keys->KeyLength[key_index]);
6612
6613 setKey.keyDirection = eSIR_TX_RX;
6614
6615 cdf_copy_macaddr(&setKey.peerMac,
6616 &pHddStaCtx->conn_info.bssId);
6617
6618 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
6619 pWextState->roamProfile.EncryptionType.
6620 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
6621 /* In the case of dynamic wep supplicant hardcodes DWEP type
6622 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
6623 * WEP-40 encryption. In this canse the key length is 5 but the
6624 * encryption type is 104 hence checking the key langht(5) and
6625 * encryption type(104) and switching encryption type to 40*/
6626 pWextState->roamProfile.EncryptionType.
6627 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
6628 pWextState->roamProfile.mcEncryptionType.
6629 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
6630 }
6631
6632 setKey.encType =
6633 pWextState->roamProfile.EncryptionType.
6634 encryptionType[0];
6635
6636 /* Issue set key request */
6637 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6638 pAdapter->sessionId, &setKey,
6639 &roamId);
6640
6641 if (0 != status) {
6642 hddLog(LOGE,
6643 FL("sme_roam_set_key failed, returned %d"),
6644 status);
6645 return -EINVAL;
6646 }
6647 }
6648 } else if (WLAN_HDD_SOFTAP == pAdapter->device_mode) {
6649 /* In SoftAp mode setting key direction for default mode */
6650 if ((eCSR_ENCRYPT_TYPE_TKIP !=
6651 pWextState->roamProfile.EncryptionType.encryptionType[0])
6652 && (eCSR_ENCRYPT_TYPE_AES !=
6653 pWextState->roamProfile.EncryptionType.
6654 encryptionType[0])) {
6655 /* Saving key direction for default key index to TX default */
6656 hdd_ap_ctx_t *pAPCtx =
6657 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6658 pAPCtx->wepKey[key_index].keyDirection =
6659 eSIR_TX_DEFAULT;
6660 }
6661 }
6662
6663 EXIT();
6664 return status;
6665}
6666
6667static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
6668 struct net_device *ndev,
6669 u8 key_index,
6670 bool unicast, bool multicast)
6671{
6672 int ret;
6673 cds_ssr_protect(__func__);
6674 ret =
6675 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
6676 multicast);
6677 cds_ssr_unprotect(__func__);
6678
6679 return ret;
6680}
6681
6682/**
6683 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
6684 * @pAdapter: Pointer to adapter
6685 * @pRoamInfo: Pointer to roam info
6686 *
6687 * Return: struct cfg80211_bss pointer
6688 */
6689struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
6690 tCsrRoamInfo *pRoamInfo)
6691{
6692 struct net_device *dev = pAdapter->dev;
6693 struct wireless_dev *wdev = dev->ieee80211_ptr;
6694 struct wiphy *wiphy = wdev->wiphy;
6695 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
6696 int chan_no;
6697 unsigned int freq;
6698 struct ieee80211_channel *chan;
6699 struct cfg80211_bss *bss = NULL;
6700
6701 ENTER();
6702
6703 if (NULL == pBssDesc) {
6704 hddLog(LOGE, FL("pBssDesc is NULL"));
6705 return bss;
6706 }
6707
6708 if (NULL == pRoamInfo->pProfile) {
6709 hddLog(LOGE, FL("Roam profile is NULL"));
6710 return bss;
6711 }
6712
6713 chan_no = pBssDesc->channelId;
6714
6715 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
6716 freq =
6717 ieee80211_channel_to_frequency(chan_no,
6718 IEEE80211_BAND_2GHZ);
6719 } else {
6720 freq =
6721 ieee80211_channel_to_frequency(chan_no,
6722 IEEE80211_BAND_5GHZ);
6723 }
6724
6725 chan = __ieee80211_get_channel(wiphy, freq);
6726
6727 if (!chan) {
6728 hddLog(LOGE, FL("chan pointer is NULL"));
6729 return NULL;
6730 }
6731
6732 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
6733 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
6734 ssId[0],
6735 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
6736 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
6737 if (bss == NULL) {
6738 hddLog(LOGE, FL("BSS not present"));
6739 } else {
6740 hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID "
6741 MAC_ADDRESS_STR),
6742 MAC_ADDR_ARRAY(pBssDesc->bssId));
6743 cfg80211_unlink_bss(wiphy, bss);
6744 }
6745 return bss;
6746}
6747
6748/**
6749 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
6750 * @pAdapter: Pointer to adapter
6751 * @bss_desc: Pointer to bss descriptor
6752 *
6753 * This function is used to inform the BSS details to nl80211 interface.
6754 *
6755 * Return: struct cfg80211_bss pointer
6756 */
6757static struct cfg80211_bss *
6758wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
6759 tSirBssDescription *bss_desc)
6760{
6761 /*
6762 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
6763 * already exists in bss data base of cfg80211 for that particular BSS
6764 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
6765 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
6766 * As of now there is no possibility to get the mgmt(probe response)
6767 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
6768 * and passing to cfg80211_inform_bss_frame.
6769 */
6770 struct net_device *dev = pAdapter->dev;
6771 struct wireless_dev *wdev = dev->ieee80211_ptr;
6772 struct wiphy *wiphy = wdev->wiphy;
6773 int chan_no = bss_desc->channelId;
6774#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
6775 qcom_ie_age *qie_age = NULL;
6776 int ie_length =
6777 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
6778#else
6779 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
6780#endif
6781 const char *ie =
6782 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
6783 unsigned int freq;
6784 struct ieee80211_channel *chan;
6785 struct ieee80211_mgmt *mgmt = NULL;
6786 struct cfg80211_bss *bss_status = NULL;
6787 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
6788 int rssi = 0;
6789 hdd_context_t *pHddCtx;
6790 int status;
6791#ifdef CONFIG_CNSS
6792 struct timespec ts;
6793#endif
6794
6795 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6796 status = wlan_hdd_validate_context(pHddCtx);
6797 if (0 != status) {
6798 hddLog(LOGE, FL("HDD context is not valid"));
6799 return NULL;
6800 }
6801
6802 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
6803 if (!mgmt) {
6804 hddLog(LOGE, FL("memory allocation failed"));
6805 return NULL;
6806 }
6807
6808 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
6809
6810#ifdef CONFIG_CNSS
6811 /* Android does not want the timestamp from the frame.
6812 Instead it wants a monotonic increasing value */
6813 cnss_get_monotonic_boottime(&ts);
6814 mgmt->u.probe_resp.timestamp =
6815 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
6816#else
6817 /* keep old behavior for non-open source (for now) */
6818 memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp,
6819 sizeof(bss_desc->timeStamp));
6820
6821#endif
6822
6823 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
6824 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
6825
6826#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
6827 /* GPS Requirement: need age ie per entry. Using vendor specific. */
6828 /* Assuming this is the last IE, copy at the end */
6829 ie_length -= sizeof(qcom_ie_age);
6830 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
6831 qie_age->element_id = QCOM_VENDOR_IE_ID;
6832 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
6833 qie_age->oui_1 = QCOM_OUI1;
6834 qie_age->oui_2 = QCOM_OUI2;
6835 qie_age->oui_3 = QCOM_OUI3;
6836 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
6837 qie_age->age =
6838 cdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
6839 qie_age->tsf_delta = bss_desc->tsf_delta;
6840#endif
6841
6842 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
6843 if (bss_desc->fProbeRsp) {
6844 mgmt->frame_control |=
6845 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
6846 } else {
6847 mgmt->frame_control |=
6848 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
6849 }
6850
6851 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
6852 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
6853 freq =
6854 ieee80211_channel_to_frequency(chan_no,
6855 IEEE80211_BAND_2GHZ);
6856 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
6857 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
6858 freq =
6859 ieee80211_channel_to_frequency(chan_no,
6860 IEEE80211_BAND_5GHZ);
6861 } else {
6862 hddLog(LOGE, FL("Invalid chan_no %d"), chan_no);
6863 kfree(mgmt);
6864 return NULL;
6865 }
6866
6867 chan = __ieee80211_get_channel(wiphy, freq);
6868 /* When the band is changed on the fly using the GUI, three things are done
6869 * 1. scan abort
6870 * 2. flush scan results from cache
6871 * 3. update the band with the new band user specified (refer to the
6872 * hdd_set_band_helper function) as part of the scan abort, message will be
6873 * queued to PE and we proceed with flushing and changinh the band.
6874 * PE will stop the scanning further and report back the results what ever
6875 * it had till now by calling the call back function.
6876 * if the time between update band and scandone call back is sufficient
6877 * enough the band change reflects in SME, SME validates the channels
6878 * and discards the channels correponding to previous band and calls back
6879 * with zero bss results. but if the time between band update and scan done
6880 * callback is very small then band change will not reflect in SME and SME
6881 * reports to HDD all the channels correponding to previous band.this is due
6882 * to race condition.but those channels are invalid to the new band and so
6883 * this function __ieee80211_get_channel will return NULL.Each time we
6884 * report scan result with this pointer null warning kernel trace is printed.
6885 * if the scan results contain large number of APs continuosly kernel
6886 * warning trace is printed and it will lead to apps watch dog bark.
6887 * So drop the bss and continue to next bss.
6888 */
6889 if (chan == NULL) {
6890 hddLog(LOGE, FL("chan pointer is NULL"));
6891 kfree(mgmt);
6892 return NULL;
6893 }
6894
6895 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
6896 rssi = (CDF_MIN((bss_desc->rssi + bss_desc->sinr), 0)) * 100;
6897
6898 hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d"),
6899 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
6900 (int)(rssi / 100));
6901
6902 bss_status =
6903 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
6904 GFP_KERNEL);
6905 kfree(mgmt);
6906 return bss_status;
6907}
6908
6909/**
6910 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
6911 * @pAdapter: Pointer to adapter
6912 * @pRoamInfo: Pointer to roam info
6913 *
6914 * This function is used to update the BSS data base of CFG8011
6915 *
6916 * Return: struct cfg80211_bss pointer
6917 */
6918struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
6919 tCsrRoamInfo *pRoamInfo)
6920{
6921 tCsrRoamConnectedProfile roamProfile;
6922 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6923 struct cfg80211_bss *bss = NULL;
6924
6925 ENTER();
6926
6927 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
6928 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
6929
6930 if (NULL != roamProfile.pBssDesc) {
6931 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
6932 roamProfile.pBssDesc);
6933
6934 if (NULL == bss)
6935 hddLog(LOG1,
6936 FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL"));
6937
6938 sme_roam_free_connect_profile(hHal, &roamProfile);
6939 } else {
6940 hddLog(LOGE, FL("roamProfile.pBssDesc is NULL"));
6941 }
6942 EXIT();
6943 return bss;
6944}
6945/**
6946 * wlan_hdd_cfg80211_update_bss() - update bss
6947 * @wiphy: Pointer to wiphy
6948 * @pAdapter: Pointer to adapter
6949 * @scan_time: scan request timestamp
6950 *
6951 * Return: zero if success, non-zero otherwise
6952 */
6953int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
6954 hdd_adapter_t *pAdapter,
6955 uint32_t scan_time)
6956{
6957 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6958 tCsrScanResultInfo *pScanResult;
6959 CDF_STATUS status = 0;
6960 tScanResultHandle pResult;
6961 struct cfg80211_bss *bss_status = NULL;
6962 hdd_context_t *pHddCtx;
6963 int ret;
6964
6965 ENTER();
6966
6967 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
6968 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
6969 NO_SESSION, pAdapter->sessionId));
6970
6971 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6972 ret = wlan_hdd_validate_context(pHddCtx);
6973 if (0 != ret) {
6974 hddLog(LOGE, FL("HDD context is not valid"));
6975 return ret;
6976 }
6977
6978 /* start getting scan results and populate cgf80211 BSS database */
6979 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
6980
6981 /* no scan results */
6982 if (NULL == pResult) {
6983 hddLog(LOGE, FL("No scan result Status %d"), status);
6984 return status;
6985 }
6986
6987 pScanResult = sme_scan_result_get_first(hHal, pResult);
6988
6989 while (pScanResult) {
6990 /*
6991 * - cfg80211_inform_bss() is not updating ie field of bss
6992 * entry if entry already exists in bss data base of cfg80211
6993 * for that particular BSS ID. Using cfg80211_inform_bss_frame
6994 * to update thebss entry instead of cfg80211_inform_bss,
6995 * But this call expects mgmt packet as input. As of now
6996 * there is no possibility to get the mgmt(probe response)
6997 * frame from PE, converting bss_desc to
6998 * ieee80211_mgmt(probe response) and passing to c
6999 * fg80211_inform_bss_frame.
7000 * - Update BSS only if beacon timestamp is later than
7001 * scan request timestamp.
7002 */
7003 if ((scan_time == 0) ||
7004 (scan_time <
7005 pScanResult->BssDescriptor.nReceivedTime)) {
7006 bss_status =
7007 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
7008 &pScanResult->BssDescriptor);
7009
7010 if (NULL == bss_status) {
7011 hdd_info("NULL returned by cfg80211_inform_bss_frame");
7012 } else {
7013 cfg80211_put_bss(
7014#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7015 wiphy,
7016#endif
7017 bss_status);
7018 }
7019 } else {
7020 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
7021 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
7022 }
7023 pScanResult = sme_scan_result_get_next(hHal, pResult);
7024 }
7025
7026 sme_scan_result_purge(hHal, pResult);
7027 /*
7028 * For SAP mode, scan is invoked by hostapd during SAP start
7029 * if hostapd is restarted, we need to flush previous scan
7030 * result so that it will reflect environment change
7031 */
7032 if (pAdapter->device_mode == WLAN_HDD_SOFTAP
7033#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
7034 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
7035#endif
7036 )
7037 sme_scan_flush_result(hHal);
7038
7039 EXIT();
7040 return 0;
7041}
7042
7043#if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7044/**
7045 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
7046 * @pAdapter: Pointer to adapter
7047 * @pRoamInfo: Pointer to roam info
7048 * @index: Index
7049 * @preauth: Preauth flag
7050 *
7051 * This function is used to notify the supplicant of a new PMKSA candidate.
7052 *
7053 * Return: 0 for success, non-zero for failure
7054 */
7055int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
7056 tCsrRoamInfo *pRoamInfo,
7057 int index, bool preauth)
7058{
7059#ifdef FEATURE_WLAN_OKC
7060 struct net_device *dev = pAdapter->dev;
7061 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
7062
7063 ENTER();
7064 hddLog(LOG1, FL("is going to notify supplicant of:"));
7065
7066 if (NULL == pRoamInfo) {
7067 hddLog(LOGP, FL("pRoamInfo is NULL"));
7068 return -EINVAL;
7069 }
7070
7071 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
7072 hddLog(LOG1, MAC_ADDRESS_STR,
7073 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
7074 cfg80211_pmksa_candidate_notify(dev, index,
7075 pRoamInfo->bssid.bytes,
7076 preauth, GFP_KERNEL);
7077 }
7078#endif /* FEATURE_WLAN_OKC */
7079 return 0;
7080}
7081#endif /* FEATURE_WLAN_LFR */
7082
7083#ifdef FEATURE_WLAN_LFR_METRICS
7084/**
7085 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
7086 * @pAdapter: Pointer to adapter
7087 * @pRoamInfo: Pointer to roam info
7088 *
7089 * 802.11r/LFR metrics reporting function to report preauth initiation
7090 *
7091 * Return: CDF status
7092 */
7093#define MAX_LFR_METRICS_EVENT_LENGTH 100
7094CDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
7095 tCsrRoamInfo *pRoamInfo)
7096{
7097 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7098 union iwreq_data wrqu;
7099
7100 ENTER();
7101
7102 if (NULL == pAdapter) {
7103 hddLog(LOGE, FL("pAdapter is NULL!"));
7104 return CDF_STATUS_E_FAILURE;
7105 }
7106
7107 /* create the event */
7108 memset(&wrqu, 0, sizeof(wrqu));
7109 memset(metrics_notification, 0, sizeof(metrics_notification));
7110
7111 wrqu.data.pointer = metrics_notification;
7112 wrqu.data.length = scnprintf(metrics_notification,
7113 sizeof(metrics_notification),
7114 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
7115 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7116
7117 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7118 metrics_notification);
7119
7120 EXIT();
7121
7122 return CDF_STATUS_SUCCESS;
7123}
7124
7125/**
7126 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7127 * @pAdapter: Pointer to adapter
7128 * @pRoamInfo: Pointer to roam info
7129 * @preauth_status: Preauth status
7130 *
7131 * 802.11r/LFR metrics reporting function to report handover initiation
7132 *
7133 * Return: CDF status
7134 */
7135CDF_STATUS
7136wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
7137 tCsrRoamInfo *pRoamInfo,
7138 bool preauth_status)
7139{
7140 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7141 union iwreq_data wrqu;
7142
7143 ENTER();
7144
7145 if (NULL == pAdapter) {
7146 hddLog(LOGE, FL("pAdapter is NULL!"));
7147 return CDF_STATUS_E_FAILURE;
7148 }
7149
7150 /* create the event */
7151 memset(&wrqu, 0, sizeof(wrqu));
7152 memset(metrics_notification, 0, sizeof(metrics_notification));
7153
7154 scnprintf(metrics_notification, sizeof(metrics_notification),
7155 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
7156 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7157
7158 if (1 == preauth_status)
7159 strlcat(metrics_notification, " true",
7160 sizeof(metrics_notification));
7161 else
7162 strlcat(metrics_notification, " false",
7163 sizeof(metrics_notification));
7164
7165 wrqu.data.pointer = metrics_notification;
7166 wrqu.data.length = strlen(metrics_notification);
7167
7168 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7169 metrics_notification);
7170
7171 EXIT();
7172
7173 return CDF_STATUS_SUCCESS;
7174}
7175
7176/**
7177 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
7178 * @pAdapter: Pointer to adapter
7179 * @pRoamInfo: Pointer to roam info
7180 *
7181 * 802.11r/LFR metrics reporting function to report handover initiation
7182 *
7183 * Return: CDF status
7184 */
7185CDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
7186 tCsrRoamInfo *pRoamInfo)
7187{
7188 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
7189 union iwreq_data wrqu;
7190
7191 ENTER();
7192
7193 if (NULL == pAdapter) {
7194 hddLog(LOGE, FL("pAdapter is NULL!"));
7195 return CDF_STATUS_E_FAILURE;
7196 }
7197
7198 /* create the event */
7199 memset(&wrqu, 0, sizeof(wrqu));
7200 memset(metrics_notification, 0, sizeof(metrics_notification));
7201
7202 wrqu.data.pointer = metrics_notification;
7203 wrqu.data.length = scnprintf(metrics_notification,
7204 sizeof(metrics_notification),
7205 "QCOM: LFR_PREAUTH_HANDOVER "
7206 MAC_ADDRESS_STR,
7207 MAC_ADDR_ARRAY(pRoamInfo->bssid));
7208
7209 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
7210 metrics_notification);
7211
7212 EXIT();
7213
7214 return CDF_STATUS_SUCCESS;
7215}
7216#endif
7217
7218/**
7219 * hdd_select_cbmode() - select channel bonding mode
7220 * @pAdapter: Pointer to adapter
7221 * @operatingChannel: Operating channel
7222 *
7223 * Return: none
7224 */
7225void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel)
7226{
7227 uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
7228 eHddDot11Mode hddDot11Mode = iniDot11Mode;
7229 chan_params_t ch_params;
7230 ch_params.ch_width =
7231 (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth;
7232
7233 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode);
7234 switch (iniDot11Mode) {
7235 case eHDD_DOT11_MODE_AUTO:
7236 case eHDD_DOT11_MODE_11ac:
7237 case eHDD_DOT11_MODE_11ac_ONLY:
7238#ifdef WLAN_FEATURE_11AC
7239 if (sme_is_feature_supported_by_fw(DOT11AC))
7240 hddDot11Mode = eHDD_DOT11_MODE_11ac;
7241 else
7242 hddDot11Mode = eHDD_DOT11_MODE_11n;
7243#else
7244 hddDot11Mode = eHDD_DOT11_MODE_11n;
7245#endif
7246 break;
7247 case eHDD_DOT11_MODE_11n:
7248 case eHDD_DOT11_MODE_11n_ONLY:
7249 hddDot11Mode = eHDD_DOT11_MODE_11n;
7250 break;
7251 default:
7252 hddDot11Mode = iniDot11Mode;
7253 break;
7254 }
7255 /* This call decides required channel bonding mode */
7256 sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal),
7257 hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode),
7258 operationChannel, 0,
7259 &ch_params);
7260}
7261
7262
7263/*
7264 * FUNCTION: wlan_hdd_cfg80211_connect_start
7265 * wlan_hdd_cfg80211_connect_start() - start connection
7266 * @pAdapter: Pointer to adapter
7267 * @ssid: Pointer ot ssid
7268 * @ssid_len: Length of ssid
7269 * @bssid: Pointer to bssid
7270 * @operatingChannel: Operating channel
7271 *
7272 * This function is used to start the association process
7273 *
7274 * Return: 0 for success, non-zero for failure
7275 */
7276int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
7277 const u8 *ssid, size_t ssid_len,
7278 const u8 *bssid_hint, const u8 *bssid,
7279 u8 operatingChannel)
7280{
7281 int status = 0;
7282 hdd_wext_state_t *pWextState;
7283 hdd_context_t *pHddCtx;
7284 uint32_t roamId;
7285 tCsrRoamProfile *pRoamProfile;
7286 eCsrAuthType RSNAuthType;
7287 tSmeConfigParams *sme_config;
7288
7289 ENTER();
7290
7291 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7292 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7293
7294 status = wlan_hdd_validate_context(pHddCtx);
7295 if (status) {
7296 hddLog(LOGE,
7297 FL("HDD context is not valid!"));
7298 return status;
7299 }
7300
7301 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
7302 hddLog(LOGE, FL("wrong SSID len"));
7303 return -EINVAL;
7304 }
7305
7306 pRoamProfile = &pWextState->roamProfile;
7307
7308 if (pRoamProfile) {
7309 hdd_station_ctx_t *pHddStaCtx;
7310 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7311
7312 if (HDD_WMM_USER_MODE_NO_QOS ==
7313 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
7314 /*QoS not enabled in cfg file */
7315 pRoamProfile->uapsd_mask = 0;
7316 } else {
7317 /*QoS enabled, update uapsd mask from cfg file */
7318 pRoamProfile->uapsd_mask =
7319 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
7320 }
7321
7322 pRoamProfile->SSIDs.numOfSSIDs = 1;
7323 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
7324 cdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
7325 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
7326 cdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
7327 ssid, ssid_len);
7328
7329 if (bssid) {
7330 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
7331 cdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
7332 bssid, CDF_MAC_ADDR_SIZE);
7333 /* Save BSSID in seperate variable as well, as RoamProfile
7334 BSSID is getting zeroed out in the association process. And in
7335 case of join failure we should send valid BSSID to supplicant
7336 */
7337 cdf_mem_copy((void *)(pWextState->req_bssId.bytes),
7338 bssid, CDF_MAC_ADDR_SIZE);
7339 } else if (bssid_hint) {
7340 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
7341 cdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
7342 bssid_hint, CDF_MAC_ADDR_SIZE);
7343 /* Save BSSID in separate variable as well, as
7344 RoamProfile BSSID is getting zeroed out in the
7345 association process. And in case of join failure
7346 we should send valid BSSID to supplicant
7347 */
7348 cdf_mem_copy((void *)(pWextState->req_bssId.bytes),
7349 bssid_hint, CDF_MAC_ADDR_SIZE);
7350 hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR),
7351 MAC_ADDR_ARRAY(bssid_hint));
7352 } else {
7353 cdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
7354 CDF_MAC_ADDR_SIZE);
7355 }
7356
7357 hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"),
7358 pRoamProfile->SSIDs.SSIDList->SSID.length,
7359 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
7360 operatingChannel);
7361
7362 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
7363 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
7364 /*set gen ie */
7365 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
7366 /*set auth */
7367 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
7368 }
7369#ifdef FEATURE_WLAN_WAPI
7370 if (pAdapter->wapi_info.nWapiMode) {
7371 hddLog(LOG1,
7372 FL("Setting WAPI AUTH Type and Encryption Mode values"));
7373 switch (pAdapter->wapi_info.wapiAuthMode) {
7374 case WAPI_AUTH_MODE_PSK:
7375 {
7376 hddLog(LOG1,
7377 FL("WAPI AUTH TYPE: PSK: %d"),
7378 pAdapter->wapi_info.wapiAuthMode);
7379 pRoamProfile->AuthType.authType[0] =
7380 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
7381 break;
7382 }
7383 case WAPI_AUTH_MODE_CERT:
7384 {
7385 hddLog(LOG1,
7386 FL("WAPI AUTH TYPE: CERT: %d"),
7387 pAdapter->wapi_info.wapiAuthMode);
7388 pRoamProfile->AuthType.authType[0] =
7389 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
7390 break;
7391 }
7392 } /* End of switch */
7393 if (pAdapter->wapi_info.wapiAuthMode ==
7394 WAPI_AUTH_MODE_PSK
7395 || pAdapter->wapi_info.wapiAuthMode ==
7396 WAPI_AUTH_MODE_CERT) {
7397 hddLog(LOG1,
7398 FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI"));
7399 pRoamProfile->AuthType.numEntries = 1;
7400 pRoamProfile->EncryptionType.numEntries = 1;
7401 pRoamProfile->EncryptionType.encryptionType[0] =
7402 eCSR_ENCRYPT_TYPE_WPI;
7403 pRoamProfile->mcEncryptionType.numEntries = 1;
7404 pRoamProfile->mcEncryptionType.
7405 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
7406 }
7407 }
7408#endif /* FEATURE_WLAN_WAPI */
7409#ifdef WLAN_FEATURE_GTK_OFFLOAD
7410 /* Initializing gtkOffloadReqParams */
7411 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7412 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
7413 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
7414 sizeof(tSirGtkOffloadParams));
7415 pHddStaCtx->gtkOffloadReqParams.ulFlags =
7416 GTK_OFFLOAD_DISABLE;
7417 }
7418#endif
7419 pRoamProfile->csrPersona = pAdapter->device_mode;
7420
7421 if (operatingChannel) {
7422 pRoamProfile->ChannelInfo.ChannelList =
7423 &operatingChannel;
7424 pRoamProfile->ChannelInfo.numOfChannels = 1;
7425 } else {
7426 pRoamProfile->ChannelInfo.ChannelList = NULL;
7427 pRoamProfile->ChannelInfo.numOfChannels = 0;
7428 }
7429 if ((WLAN_HDD_IBSS == pAdapter->device_mode)
7430 && operatingChannel) {
7431 /*
7432 * Need to post the IBSS power save parameters
7433 * to WMA. WMA will configure this parameters
7434 * to firmware if power save is enabled by the
7435 * firmware.
7436 */
7437 status = hdd_set_ibss_power_save_params(pAdapter);
7438
7439 if (CDF_STATUS_SUCCESS != status) {
7440 hddLog(LOGE,
7441 FL("Set IBSS Power Save Params Failed"));
7442 return -EINVAL;
7443 }
7444 hdd_select_cbmode(pAdapter, operatingChannel);
7445 }
7446
7447 if (pHddCtx->config->policy_manager_enabled &&
7448 (true == cds_is_connection_in_progress(pHddCtx))) {
7449 hdd_err("Connection refused: conn in progress");
7450 return -EINVAL;
7451 }
7452
7453 /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect()
7454 * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state
7455 * If direct path, conn_state will be accordingly changed to NotConnected or Associated
7456 * by either hdd_association_completion_handler() or hdd_dis_connect_handler() in sme_RoamCallback()
7457 * if sme_RomConnect is to be queued, Connecting state will remain until it is completed.
7458 */
7459 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7460 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) {
7461 hddLog(LOG1,
7462 FL("Set HDD connState to eConnectionState_Connecting"));
7463 hdd_conn_set_connection_state(pAdapter,
7464 eConnectionState_Connecting);
7465 }
7466
7467 /* After 8-way handshake supplicant should give the scan command
7468 * in that it update the additional IEs, But because of scan
7469 * enhancements, the supplicant is not issuing the scan command now.
7470 * So the unicast frames which are sent from the host are not having
7471 * the additional IEs. If it is P2P CLIENT and there is no additional
7472 * IE present in roamProfile, then use the addtional IE form scan_info
7473 */
7474
7475 if ((pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) &&
7476 (!pRoamProfile->pAddIEScan)) {
7477 pRoamProfile->pAddIEScan =
7478 &pAdapter->scan_info.scanAddIE.addIEdata[0];
7479 pRoamProfile->nAddIEScanLength =
7480 pAdapter->scan_info.scanAddIE.length;
7481 }
7482 /*
7483 * When policy manager is enabled from ini file, we shouldn't
7484 * check for other concurrency rules.
7485 */
7486 if (!pHddCtx->config->policy_manager_enabled) {
7487 cds_handle_conc_rule1(pHddCtx, pAdapter,
7488 pRoamProfile);
7489 if (true != cds_handle_conc_rule2(pHddCtx,
7490 pAdapter, pRoamProfile, &roamId))
7491 return 0;
7492 }
7493
7494 sme_config = cdf_mem_malloc(sizeof(*sme_config));
7495 if (!sme_config) {
7496 hdd_err("unable to allocate sme_config");
7497 return -ENOMEM;
7498 }
7499 cdf_mem_zero(sme_config, sizeof(*sme_config));
7500 sme_get_config_param(pHddCtx->hHal, sme_config);
7501 /* These values are not sessionized. So, any change in these SME
7502 * configs on an older or parallel interface will affect the
7503 * cb mode. So, restoring the default INI params before starting
7504 * interfaces such as sta, cli etc.,
7505 */
7506 sme_config->csrConfig.channelBondingMode5GHz =
7507 pHddCtx->config->nChannelBondingMode5GHz;
7508 sme_config->csrConfig.channelBondingMode24GHz =
7509 pHddCtx->config->nChannelBondingMode24GHz;
7510 sme_update_config(pHddCtx->hHal, sme_config);
7511 cdf_mem_free(sme_config);
7512
7513 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
7514 pAdapter->sessionId, pRoamProfile,
7515 &roamId);
7516
7517 if ((CDF_STATUS_SUCCESS != status) &&
7518 (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7519 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) {
7520 hddLog(LOGE,
7521 FL("sme_roam_connect (session %d) failed with "
7522 "status %d. -> NotConnected"),
7523 pAdapter->sessionId, status);
7524 /* change back to NotAssociated */
7525 hdd_conn_set_connection_state(pAdapter,
7526 eConnectionState_NotConnected);
7527 }
7528
7529 pRoamProfile->ChannelInfo.ChannelList = NULL;
7530 pRoamProfile->ChannelInfo.numOfChannels = 0;
7531
7532 } else {
7533 hddLog(LOGE, FL("No valid Roam profile"));
7534 return -EINVAL;
7535 }
7536 EXIT();
7537 return status;
7538}
7539
7540/**
7541 * wlan_hdd_cfg80211_set_auth_type() - set auth type
7542 * @pAdapter: Pointer to adapter
7543 * @auth_type: Auth type
7544 *
7545 * This function is used to set the authentication type (OPEN/SHARED).
7546 *
7547 * Return: 0 for success, non-zero for failure
7548 */
7549static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
7550 enum nl80211_auth_type auth_type)
7551{
7552 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7553 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7554
7555 ENTER();
7556
7557 /*set authentication type */
7558 switch (auth_type) {
7559 case NL80211_AUTHTYPE_AUTOMATIC:
7560 hddLog(LOG1,
7561 FL("set authentication type to AUTOSWITCH"));
7562 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
7563 break;
7564
7565 case NL80211_AUTHTYPE_OPEN_SYSTEM:
7566#ifdef WLAN_FEATURE_VOWIFI_11R
7567 case NL80211_AUTHTYPE_FT:
7568#endif /* WLAN_FEATURE_VOWIFI_11R */
7569 hddLog(LOG1,
7570 FL("set authentication type to OPEN"));
7571 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
7572 break;
7573
7574 case NL80211_AUTHTYPE_SHARED_KEY:
7575 hddLog(LOG1,
7576 FL("set authentication type to SHARED"));
7577 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
7578 break;
7579#ifdef FEATURE_WLAN_ESE
7580 case NL80211_AUTHTYPE_NETWORK_EAP:
7581 hddLog(LOG1,
7582 FL("set authentication type to CCKM WPA"));
7583 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
7584 break;
7585#endif
7586
7587 default:
7588 hddLog(LOGE,
7589 FL("Unsupported authentication type %d"), auth_type);
7590 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
7591 return -EINVAL;
7592 }
7593
7594 pWextState->roamProfile.AuthType.authType[0] =
7595 pHddStaCtx->conn_info.authType;
7596 return 0;
7597}
7598
7599/**
7600 * wlan_hdd_set_akm_suite() - set key management type
7601 * @pAdapter: Pointer to adapter
7602 * @key_mgmt: Key management type
7603 *
7604 * This function is used to set the key mgmt type(PSK/8021x).
7605 *
7606 * Return: 0 for success, non-zero for failure
7607 */
7608static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
7609{
7610 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7611
7612 ENTER();
7613
7614#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
7615#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
7616 /*set key mgmt type */
7617 switch (key_mgmt) {
7618 case WLAN_AKM_SUITE_PSK:
7619 case WLAN_AKM_SUITE_PSK_SHA256:
7620#ifdef WLAN_FEATURE_VOWIFI_11R
7621 case WLAN_AKM_SUITE_FT_PSK:
7622#endif
7623 hddLog(LOG1, FL("setting key mgmt type to PSK"));
7624 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
7625 break;
7626
7627 case WLAN_AKM_SUITE_8021X_SHA256:
7628 case WLAN_AKM_SUITE_8021X:
7629#ifdef WLAN_FEATURE_VOWIFI_11R
7630 case WLAN_AKM_SUITE_FT_8021X:
7631#endif
7632 hddLog(LOG1,
7633 FL("setting key mgmt type to 8021x"));
7634 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
7635 break;
7636#ifdef FEATURE_WLAN_ESE
7637#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
7638#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
7639 case WLAN_AKM_SUITE_CCKM:
7640 hddLog(LOG1,
7641 FL("setting key mgmt type to CCKM"));
7642 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
7643 break;
7644#endif
7645#ifndef WLAN_AKM_SUITE_OSEN
7646#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
7647#endif
7648 case WLAN_AKM_SUITE_OSEN:
7649 hddLog(LOG1,
7650 FL("setting key mgmt type to OSEN"));
7651 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
7652 break;
7653
7654 default:
7655 hddLog(LOGE,
7656 FL("Unsupported key mgmt type %d"), key_mgmt);
7657 return -EINVAL;
7658
7659 }
7660 return 0;
7661}
7662
7663/**
7664 * wlan_hdd_cfg80211_set_cipher() - set encryption type
7665 * @pAdapter: Pointer to adapter
7666 * @cipher: Cipher type
7667 * @ucast: Unicast flag
7668 *
7669 * This function is used to set the encryption type
7670 * (NONE/WEP40/WEP104/TKIP/CCMP).
7671 *
7672 * Return: 0 for success, non-zero for failure
7673 */
7674static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
7675 u32 cipher, bool ucast)
7676{
7677 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
7678 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7679 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7680
7681 ENTER();
7682
7683 if (!cipher) {
7684 hddLog(LOGE,
7685 FL("received cipher %d - considering none"), cipher);
7686 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
7687 } else {
7688
7689 /*set encryption method */
7690 switch (cipher) {
7691 case IW_AUTH_CIPHER_NONE:
7692 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
7693 break;
7694
7695 case WLAN_CIPHER_SUITE_WEP40:
7696 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
7697 break;
7698
7699 case WLAN_CIPHER_SUITE_WEP104:
7700 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
7701 break;
7702
7703 case WLAN_CIPHER_SUITE_TKIP:
7704 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
7705 break;
7706
7707 case WLAN_CIPHER_SUITE_CCMP:
7708 encryptionType = eCSR_ENCRYPT_TYPE_AES;
7709 break;
7710#ifdef FEATURE_WLAN_WAPI
7711 case WLAN_CIPHER_SUITE_SMS4:
7712 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
7713 break;
7714#endif
7715
7716#ifdef FEATURE_WLAN_ESE
7717 case WLAN_CIPHER_SUITE_KRK:
7718 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
7719 break;
7720#ifdef WLAN_FEATURE_ROAM_OFFLOAD
7721 case WLAN_CIPHER_SUITE_BTK:
7722 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
7723 break;
7724#endif
7725#endif
7726 default:
7727 hddLog(LOGE,
7728 FL("Unsupported cipher type %d"), cipher);
7729 return -EOPNOTSUPP;
7730 }
7731 }
7732
7733 if (ucast) {
7734 hddLog(LOG1,
7735 FL("setting unicast cipher type to %d"), encryptionType);
7736 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
7737 pWextState->roamProfile.EncryptionType.numEntries = 1;
7738 pWextState->roamProfile.EncryptionType.encryptionType[0] =
7739 encryptionType;
7740 } else {
7741 hddLog(LOG1,
7742 FL("setting mcast cipher type to %d"), encryptionType);
7743 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
7744 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
7745 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
7746 encryptionType;
7747 }
7748
7749 return 0;
7750}
7751
7752/**
7753 * wlan_hdd_cfg80211_set_ie() - set IEs
7754 * @pAdapter: Pointer to adapter
7755 * @ie: Pointer ot ie
7756 * @ie: IE length
7757 *
7758 * Return: 0 for success, non-zero for failure
7759 */
7760int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
7761 size_t ie_len)
7762{
7763 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7764 const uint8_t *genie = ie;
7765 uint16_t remLen = ie_len;
7766#ifdef FEATURE_WLAN_WAPI
7767 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
7768 u16 *tmp;
7769 uint16_t akmsuiteCount;
7770 int *akmlist;
7771#endif
7772 ENTER();
7773
7774 /* clear previous assocAddIE */
7775 pWextState->assocAddIE.length = 0;
7776 pWextState->roamProfile.bWPSAssociation = false;
7777 pWextState->roamProfile.bOSENAssociation = false;
7778
7779 while (remLen >= 2) {
7780 uint16_t eLen = 0;
7781 uint8_t elementId;
7782 elementId = *genie++;
7783 eLen = *genie++;
7784 remLen -= 2;
7785
7786 hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), elementId, eLen);
7787
7788 switch (elementId) {
7789 case DOT11F_EID_WPA:
7790 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
7791 hddLog(LOGE, FL("Invalid WPA IE"));
7792 return -EINVAL;
7793 } else if (0 ==
7794 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
7795 uint16_t curAddIELen =
7796 pWextState->assocAddIE.length;
7797 hddLog(LOG1,
7798 FL("Set WPS IE(len %d)"), eLen + 2);
7799
7800 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7801 (pWextState->assocAddIE.length + eLen)) {
7802 hddLog(LOGE,
7803 FL("Cannot accommodate assocAddIE. Need bigger buffer space"));
7804 CDF_ASSERT(0);
7805 return -ENOMEM;
7806 }
7807 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
7808 memcpy(pWextState->assocAddIE.addIEdata +
7809 curAddIELen, genie - 2, eLen + 2);
7810 pWextState->assocAddIE.length += eLen + 2;
7811
7812 pWextState->roamProfile.bWPSAssociation = true;
7813 pWextState->roamProfile.pAddIEAssoc =
7814 pWextState->assocAddIE.addIEdata;
7815 pWextState->roamProfile.nAddIEAssocLength =
7816 pWextState->assocAddIE.length;
7817 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
7818 hddLog(LOG1,
7819 FL("Set WPA IE (len %d)"), eLen + 2);
7820 memset(pWextState->WPARSNIE, 0,
7821 MAX_WPA_RSN_IE_LEN);
7822 memcpy(pWextState->WPARSNIE, genie - 2,
7823 (eLen + 2));
7824 pWextState->roamProfile.pWPAReqIE =
7825 pWextState->WPARSNIE;
7826 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
7827 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
7828 P2P_OUI_TYPE_SIZE))) {
7829 uint16_t curAddIELen =
7830 pWextState->assocAddIE.length;
7831 hddLog(LOG1,
7832 FL("Set P2P IE(len %d)"), eLen + 2);
7833
7834 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7835 (pWextState->assocAddIE.length + eLen)) {
7836 hddLog(LOGE,
7837 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
7838 CDF_ASSERT(0);
7839 return -ENOMEM;
7840 }
7841 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
7842 memcpy(pWextState->assocAddIE.addIEdata +
7843 curAddIELen, genie - 2, eLen + 2);
7844 pWextState->assocAddIE.length += eLen + 2;
7845
7846 pWextState->roamProfile.pAddIEAssoc =
7847 pWextState->assocAddIE.addIEdata;
7848 pWextState->roamProfile.nAddIEAssocLength =
7849 pWextState->assocAddIE.length;
7850 }
7851#ifdef WLAN_FEATURE_WFD
7852 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
7853 WFD_OUI_TYPE_SIZE)) &&
7854 /* Consider WFD IE, only for P2P Client */
7855 (WLAN_HDD_P2P_CLIENT ==
7856 pAdapter->device_mode)) {
7857 uint16_t curAddIELen =
7858 pWextState->assocAddIE.length;
7859 hddLog(LOG1,
7860 FL("Set WFD IE(len %d)"), eLen + 2);
7861
7862 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7863 (pWextState->assocAddIE.length + eLen)) {
7864 hddLog(LOGE,
7865 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
7866 CDF_ASSERT(0);
7867 return -ENOMEM;
7868 }
7869 /* WFD IE is saved to Additional IE ; it should
7870 * be accumulated to handle WPS IE + P2P IE +
7871 * WFD IE */
7872 memcpy(pWextState->assocAddIE.addIEdata +
7873 curAddIELen, genie - 2, eLen + 2);
7874 pWextState->assocAddIE.length += eLen + 2;
7875
7876 pWextState->roamProfile.pAddIEAssoc =
7877 pWextState->assocAddIE.addIEdata;
7878 pWextState->roamProfile.nAddIEAssocLength =
7879 pWextState->assocAddIE.length;
7880 }
7881#endif
7882 /* Appending HS 2.0 Indication Element in Assiciation Request */
7883 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
7884 HS20_OUI_TYPE_SIZE))) {
7885 uint16_t curAddIELen =
7886 pWextState->assocAddIE.length;
7887 hddLog(LOG1,
7888 FL("Set HS20 IE(len %d)"), eLen + 2);
7889
7890 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7891 (pWextState->assocAddIE.length + eLen)) {
7892 hddLog(LOGE,
7893 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
7894 CDF_ASSERT(0);
7895 return -ENOMEM;
7896 }
7897 memcpy(pWextState->assocAddIE.addIEdata +
7898 curAddIELen, genie - 2, eLen + 2);
7899 pWextState->assocAddIE.length += eLen + 2;
7900
7901 pWextState->roamProfile.pAddIEAssoc =
7902 pWextState->assocAddIE.addIEdata;
7903 pWextState->roamProfile.nAddIEAssocLength =
7904 pWextState->assocAddIE.length;
7905 }
7906 /* Appending OSEN Information Element in Assiciation Request */
7907 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
7908 OSEN_OUI_TYPE_SIZE))) {
7909 uint16_t curAddIELen =
7910 pWextState->assocAddIE.length;
7911 hddLog(LOG1,
7912 FL("Set OSEN IE(len %d)"), eLen + 2);
7913
7914 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7915 (pWextState->assocAddIE.length + eLen)) {
7916 hddLog(LOGE,
7917 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
7918 CDF_ASSERT(0);
7919 return -ENOMEM;
7920 }
7921 memcpy(pWextState->assocAddIE.addIEdata +
7922 curAddIELen, genie - 2, eLen + 2);
7923 pWextState->assocAddIE.length += eLen + 2;
7924
7925 pWextState->roamProfile.bOSENAssociation = true;
7926 pWextState->roamProfile.pAddIEAssoc =
7927 pWextState->assocAddIE.addIEdata;
7928 pWextState->roamProfile.nAddIEAssocLength =
7929 pWextState->assocAddIE.length;
7930 } else {
7931 uint16_t add_ie_len =
7932 pWextState->assocAddIE.length;
7933
7934 hdd_info("Set OSEN IE(len %d)", eLen + 2);
7935
7936 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7937 (pWextState->assocAddIE.length + eLen)) {
7938 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
7939 CDF_ASSERT(0);
7940 return -ENOMEM;
7941 }
7942
7943 memcpy(pWextState->assocAddIE.addIEdata +
7944 add_ie_len, genie - 2, eLen + 2);
7945 pWextState->assocAddIE.length += eLen + 2;
7946
7947 pWextState->roamProfile.pAddIEAssoc =
7948 pWextState->assocAddIE.addIEdata;
7949 pWextState->roamProfile.nAddIEAssocLength =
7950 pWextState->assocAddIE.length;
7951 }
7952 break;
7953 case DOT11F_EID_RSN:
7954 hddLog(LOG1, FL("Set RSN IE(len %d)"), eLen + 2);
7955 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
7956 memcpy(pWextState->WPARSNIE, genie - 2,
7957 (eLen + 2));
7958 pWextState->roamProfile.pRSNReqIE =
7959 pWextState->WPARSNIE;
7960 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
7961 break;
7962 /*
7963 * Appending Extended Capabilities with Interworking bit set
7964 * in Assoc Req.
7965 *
7966 * In assoc req this EXT Cap will only be taken into account if
7967 * interworkingService bit is set to 1. Currently
7968 * driver is only interested in interworkingService capability
7969 * from supplicant. If in future any other EXT Cap info is
7970 * required from supplicat, it needs to be handled while
7971 * sending Assoc Req in LIM.
7972 */
7973 case DOT11F_EID_EXTCAP:
7974 {
7975 uint16_t curAddIELen =
7976 pWextState->assocAddIE.length;
7977 hddLog(LOG1,
7978 FL("Set Extended CAPS IE(len %d)"), eLen + 2);
7979
7980 if (SIR_MAC_MAX_ADD_IE_LENGTH <
7981 (pWextState->assocAddIE.length + eLen)) {
7982 hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space"));
7983 CDF_ASSERT(0);
7984 return -ENOMEM;
7985 }
7986 memcpy(pWextState->assocAddIE.addIEdata +
7987 curAddIELen, genie - 2, eLen + 2);
7988 pWextState->assocAddIE.length += eLen + 2;
7989
7990 pWextState->roamProfile.pAddIEAssoc =
7991 pWextState->assocAddIE.addIEdata;
7992 pWextState->roamProfile.nAddIEAssocLength =
7993 pWextState->assocAddIE.length;
7994 break;
7995 }
7996#ifdef FEATURE_WLAN_WAPI
7997 case WLAN_EID_WAPI:
7998 /* Setting WAPI Mode to ON=1 */
7999 pAdapter->wapi_info.nWapiMode = 1;
8000 hddLog(LOG1,
8001 FL("WAPI MODE IS %u"), pAdapter->wapi_info.nWapiMode);
8002 tmp = (u16 *) ie;
8003 tmp = tmp + 2; /* Skip element Id and Len, Version */
8004 akmsuiteCount = WPA_GET_LE16(tmp);
8005 tmp = tmp + 1;
8006 akmlist = (int *)(tmp);
8007 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
8008 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
8009 } else {
8010 hddLog(LOGE,
8011 FL("Invalid akmSuite count"));
8012 CDF_ASSERT(0);
8013 return -EINVAL;
8014 }
8015
8016 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
8017 hddLog(LOG1,
8018 FL("WAPI AUTH MODE SET TO PSK"));
8019 pAdapter->wapi_info.wapiAuthMode =
8020 WAPI_AUTH_MODE_PSK;
8021 }
8022 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
8023 hddLog(LOG1,
8024 FL("WAPI AUTH MODE SET TO CERTIFICATE"));
8025 pAdapter->wapi_info.wapiAuthMode =
8026 WAPI_AUTH_MODE_CERT;
8027 }
8028 break;
8029#endif
8030 default:
8031 hddLog(LOGE,
8032 FL("Set UNKNOWN IE %X"), elementId);
8033 /* when Unknown IE is received we should break and continue
8034 * to the next IE in the buffer instead we were returning
8035 * so changing this to break */
8036 break;
8037 }
8038 genie += eLen;
8039 remLen -= eLen;
8040 }
8041 EXIT();
8042 return 0;
8043}
8044
8045/**
8046 * hdd_is_wpaie_present() - check for WPA ie
8047 * @ie: Pointer to ie
8048 * @ie_len: Ie length
8049 *
8050 * Parse the received IE to find the WPA IE
8051 *
8052 * Return: true if wpa ie is found else false
8053 */
8054static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
8055{
8056 uint8_t eLen = 0;
8057 uint16_t remLen = ie_len;
8058 uint8_t elementId = 0;
8059
8060 while (remLen >= 2) {
8061 elementId = *ie++;
8062 eLen = *ie++;
8063 remLen -= 2;
8064 if (eLen > remLen) {
8065 hddLog(CDF_TRACE_LEVEL_ERROR,
8066 "%s: IE length is wrong %d", __func__, eLen);
8067 return false;
8068 }
8069 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
8070 /* OUI - 0x00 0X50 0XF2
8071 * WPA Information Element - 0x01
8072 * WPA version - 0x01
8073 */
8074 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
8075 return true;
8076 }
8077 ie += eLen;
8078 remLen -= eLen;
8079 }
8080 return false;
8081}
8082
8083/**
8084 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
8085 * @pAdapter: Pointer to adapter
8086 * @req: Pointer to security parameters
8087 *
8088 * Return: 0 for success, non-zero for failure
8089 */
8090int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
8091 struct cfg80211_connect_params *req)
8092{
8093 int status = 0;
8094 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8095 ENTER();
8096
8097 /*set wpa version */
8098 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
8099
8100 if (req->crypto.wpa_versions) {
8101 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
8102 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
8103 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
8104 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
8105 }
8106 }
8107
8108 hddLog(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion);
8109
8110 /*set authentication type */
8111 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
8112
8113 if (0 > status) {
8114 hddLog(LOGE, FL("failed to set authentication type "));
8115 return status;
8116 }
8117
8118 /*set key mgmt type */
8119 if (req->crypto.n_akm_suites) {
8120 status =
8121 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
8122 if (0 > status) {
8123 hddLog(LOGE, FL("failed to set akm suite"));
8124 return status;
8125 }
8126 }
8127
8128 /*set pairwise cipher type */
8129 if (req->crypto.n_ciphers_pairwise) {
8130 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
8131 req->crypto.
8132 ciphers_pairwise[0],
8133 true);
8134 if (0 > status) {
8135 hddLog(LOGE, FL("failed to set unicast cipher type"));
8136 return status;
8137 }
8138 } else {
8139 /*Reset previous cipher suite to none */
8140 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
8141 if (0 > status) {
8142 hddLog(LOGE, FL("failed to set unicast cipher type"));
8143 return status;
8144 }
8145 }
8146
8147 /*set group cipher type */
8148 status =
8149 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
8150 false);
8151
8152 if (0 > status) {
8153 hddLog(LOGE, FL("failed to set mcast cipher type"));
8154 return status;
8155 }
8156#ifdef WLAN_FEATURE_11W
8157 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
8158#endif
8159
8160 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
8161 if (req->ie_len) {
8162 status =
8163 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
8164 if (0 > status) {
8165 hddLog(LOGE, FL("failed to parse the WPA/RSN IE"));
8166 return status;
8167 }
8168 }
8169
8170 /*incase of WEP set default key information */
8171 if (req->key && req->key_len) {
8172 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
8173 || (WLAN_CIPHER_SUITE_WEP104 ==
8174 req->crypto.ciphers_pairwise[0])
8175 ) {
8176 if (IW_AUTH_KEY_MGMT_802_1X
8177 ==
8178 (pWextState->
8179 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
8180 hddLog(LOGE,
8181 FL("Dynamic WEP not supported"));
8182 return -EOPNOTSUPP;
8183 } else {
8184 u8 key_len = req->key_len;
8185 u8 key_idx = req->key_idx;
8186
8187 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
8188 key_len)
8189 && (CSR_MAX_NUM_KEY > key_idx)
8190 ) {
8191 hddLog(LOG1,
8192 FL("setting default wep key, key_idx = %hu key_len %hu"),
8193 key_idx, key_len);
8194 cdf_mem_copy(&pWextState->roamProfile.
8195 Keys.
8196 KeyMaterial[key_idx][0],
8197 req->key, key_len);
8198 pWextState->roamProfile.Keys.
8199 KeyLength[key_idx] = (u8) key_len;
8200 pWextState->roamProfile.Keys.
8201 defaultIndex = (u8) key_idx;
8202 }
8203 }
8204 }
8205 }
8206
8207 return status;
8208}
8209
8210/**
8211 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
8212 * @pAdapter: Pointer to adapter
8213 *
8214 * This function is used to disconnect from previous connection
8215 *
8216 * Return: 0 for success, non-zero for failure
8217 */
8218static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
8219{
8220 unsigned long rc;
8221 hdd_station_ctx_t *pHddStaCtx;
8222 eMib_dot11DesiredBssType connectedBssType;
8223
8224 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8225
8226 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
8227
8228 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
8229 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
8230 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
8231 hdd_conn_set_connection_state(pAdapter,
8232 eConnectionState_Disconnecting);
8233 /* Issue disconnect to CSR */
8234 INIT_COMPLETION(pAdapter->disconnect_comp_var);
8235 if (CDF_STATUS_SUCCESS ==
8236 sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8237 pAdapter->sessionId,
8238 eCSR_DISCONNECT_REASON_UNSPECIFIED)) {
8239 rc = wait_for_completion_timeout(&pAdapter->
8240 disconnect_comp_var,
8241 msecs_to_jiffies
8242 (WLAN_WAIT_TIME_DISCONNECT));
8243 if (!rc) {
8244 hddLog(LOGE,
8245 FL("Sme disconnect event timed out session Id %d staDebugState %d"),
8246 pAdapter->sessionId,
8247 pHddStaCtx->staDebugState);
8248 return -EALREADY;
8249 }
8250 }
8251 } else if (eConnectionState_Disconnecting ==
8252 pHddStaCtx->conn_info.connState) {
8253 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
8254 msecs_to_jiffies
8255 (WLAN_WAIT_TIME_DISCONNECT));
8256 if (!rc) {
8257 hddLog(LOGE,
8258 FL("Disconnect event timed out session Id %d staDebugState %d"),
8259 pAdapter->sessionId, pHddStaCtx->staDebugState);
8260 return -EALREADY;
8261 }
8262 }
8263
8264 return 0;
8265}
8266
8267/**
8268 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
8269 * @wiphy: Pointer to wiphy
8270 * @dev: Pointer to network device
8271 * @req: Pointer to cfg80211 connect request
8272 *
8273 * This function is used to start the association process
8274 *
8275 * Return: 0 for success, non-zero for failure
8276 */
8277static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8278 struct net_device *ndev,
8279 struct cfg80211_connect_params *req)
8280{
8281 int status;
8282 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8283 hdd_context_t *pHddCtx;
8284
8285 ENTER();
8286
8287 if (CDF_FTM_MODE == hdd_get_conparam()) {
8288 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8289 return -EINVAL;
8290 }
8291
8292 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
8293 TRACE_CODE_HDD_CFG80211_CONNECT,
8294 pAdapter->sessionId, pAdapter->device_mode));
8295 hddLog(LOG1, FL("Device_mode %s(%d)"),
8296 hdd_device_mode_to_string(pAdapter->device_mode),
8297 pAdapter->device_mode);
8298
8299 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION &&
8300 pAdapter->device_mode != WLAN_HDD_P2P_CLIENT) {
8301 hddLog(LOGE, FL("Device_mode %s(%d) is not supported"),
8302 hdd_device_mode_to_string(pAdapter->device_mode),
8303 pAdapter->device_mode);
8304 return -EINVAL;
8305 }
8306
8307 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8308 if (!pHddCtx) {
8309 hddLog(LOGE, FL("HDD context is null"));
8310 return -EINVAL;
8311 }
8312
8313 status = wlan_hdd_validate_context(pHddCtx);
8314 if (0 != status) {
8315 hddLog(LOGE, FL("HDD context is not valid"));
8316 return status;
8317 }
8318 if (req->channel) {
8319 if (!cds_allow_concurrency(pHddCtx,
8320 cds_convert_device_mode_to_hdd_type(
8321 pAdapter->device_mode),
8322 req->channel->hw_value, HW_MODE_20_MHZ)) {
8323 hdd_err("This concurrency combination is not allowed");
8324 return -ECONNREFUSED;
8325 }
8326 } else {
8327 if (!cds_allow_concurrency(pHddCtx,
8328 cds_convert_device_mode_to_hdd_type(
8329 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
8330 hdd_err("This concurrency combination is not allowed");
8331 return -ECONNREFUSED;
8332 }
8333 }
8334#if defined(FEATURE_WLAN_LFR)
8335 wlan_hdd_disable_roaming(pAdapter);
8336#endif
8337
8338 /*Try disconnecting if already in connected state */
8339 status = wlan_hdd_try_disconnect(pAdapter);
8340 if (0 > status) {
8341 hddLog(LOGE,
8342 FL("Failed to disconnect the existing connection"));
8343 return -EALREADY;
8344 }
8345
8346 /*initialise security parameters */
8347 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
8348
8349 if (0 > status) {
8350 hddLog(LOGE,
8351 FL("failed to set security params"));
8352 return status;
8353 }
8354
8355 if (req->channel) {
8356 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
8357 req->ssid_len,
8358 req->bssid,
8359#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \
8360 defined(CFG80211_BSSID_HINT_BACKPORT)
8361 req->bssid_hint,
8362#else
8363 NULL,
8364#endif
8365 req->channel->
8366 hw_value);
8367 } else {
8368 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
8369 req->ssid_len,
8370 req->bssid,
8371#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \
8372 defined(CFG80211_BSSID_HINT_BACKPORT)
8373 req->bssid_hint,
8374#else
8375 NULL,
8376#endif
8377 0);
8378 }
8379
8380 if (0 > status) {
8381 hddLog(LOGE, FL("connect failed"));
8382 return status;
8383 }
8384 EXIT();
8385 return status;
8386}
8387
8388/**
8389 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
8390 * @wiphy: Pointer to wiphy
8391 * @dev: Pointer to network device
8392 * @req: Pointer to cfg80211 connect request
8393 *
8394 * Return: 0 for success, non-zero for failure
8395 */
8396static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
8397 struct net_device *ndev,
8398 struct cfg80211_connect_params *req)
8399{
8400 int ret;
8401 cds_ssr_protect(__func__);
8402 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
8403 cds_ssr_unprotect(__func__);
8404
8405 return ret;
8406}
8407
8408/**
8409 * wlan_hdd_disconnect() - hdd disconnect api
8410 * @pAdapter: Pointer to adapter
8411 * @reason: Disconnect reason code
8412 *
8413 * This function is used to issue a disconnect request to SME
8414 *
8415 * Return: 0 for success, non-zero for failure
8416 */
8417int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
8418{
8419 int status, result = 0;
8420 unsigned long rc;
8421 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8422 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8423
8424 status = wlan_hdd_validate_context(pHddCtx);
8425
8426 if (0 != status) {
8427 hddLog(LOGE,
8428 FL("HDD context is not valid"));
8429 return status;
8430 }
8431
8432 /*stop tx queues */
8433 hddLog(LOG1, FL("Disabling queues"));
8434 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
8435 WLAN_CONTROL_PATH);
8436 hddLog(LOG1,
8437 FL("Set HDD connState to eConnectionState_Disconnecting"));
8438 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
8439 INIT_COMPLETION(pAdapter->disconnect_comp_var);
8440
8441 /*issue disconnect */
8442
8443 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8444 pAdapter->sessionId, reason);
8445 if (CDF_STATUS_CMD_NOT_QUEUED == status) {
8446 hddLog(LOG1, FL("status = %d, already disconnected"),
8447 (int)status);
8448 goto disconnected;
8449 } else if (0 != status) {
8450 hddLog(LOGE,
8451 FL("csr_roam_disconnect failure, returned %d"),
8452 (int)status);
8453 pHddStaCtx->staDebugState = status;
8454 result = -EINVAL;
8455 goto disconnected;
8456 }
8457 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
8458 msecs_to_jiffies
8459 (WLAN_WAIT_TIME_DISCONNECT));
8460
8461 if (!rc) {
8462 hddLog(LOGE,
8463 FL("Failed to disconnect, timed out"));
8464 result = -ETIMEDOUT;
8465 }
8466disconnected:
8467 hddLog(LOG1,
8468 FL("Set HDD connState to eConnectionState_NotConnected"));
8469 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
8470#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
8471 /* Sending disconnect event to userspace for kernel version < 3.11
8472 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
8473 */
8474 hddLog(LOG1, FL("Send disconnected event to userspace"));
8475 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
8476 NULL, 0, GFP_KERNEL);
8477#endif
8478
8479 return result;
8480}
8481
8482/**
8483 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
8484 * @wiphy: Pointer to wiphy
8485 * @dev: Pointer to network device
8486 * @reason: Disconnect reason code
8487 *
8488 * This function is used to issue a disconnect request to SME
8489 *
8490 * Return: 0 for success, non-zero for failure
8491 */
8492static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
8493 struct net_device *dev, u16 reason)
8494{
8495 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8496 int status;
8497 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8498 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8499#ifdef FEATURE_WLAN_TDLS
8500 uint8_t staIdx;
8501#endif
8502
8503 ENTER();
8504
8505 if (CDF_FTM_MODE == hdd_get_conparam()) {
8506 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8507 return -EINVAL;
8508 }
8509
8510 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
8511 TRACE_CODE_HDD_CFG80211_DISCONNECT,
8512 pAdapter->sessionId, reason));
8513 hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"),
8514 hdd_device_mode_to_string(pAdapter->device_mode),
8515 pAdapter->device_mode, reason);
8516
8517 status = wlan_hdd_validate_context(pHddCtx);
8518
8519 if (0 != status) {
8520 hddLog(LOGE, FL("HDD context is not valid"));
8521 return status;
8522 }
8523
8524 /* Issue disconnect request to SME, if station is in connected state */
8525 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
8526 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
8527 eCsrRoamDisconnectReason reasonCode =
8528 eCSR_DISCONNECT_REASON_UNSPECIFIED;
8529 hdd_scaninfo_t *pScanInfo;
8530
8531 switch (reason) {
8532 case WLAN_REASON_MIC_FAILURE:
8533 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
8534 break;
8535
8536 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
8537 case WLAN_REASON_DISASSOC_AP_BUSY:
8538 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
8539 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
8540 break;
8541
8542 case WLAN_REASON_PREV_AUTH_NOT_VALID:
8543 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
8544 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
8545 break;
8546
8547 case WLAN_REASON_DEAUTH_LEAVING:
8548 reasonCode =
8549 pHddCtx->config->
8550 gEnableDeauthToDisassocMap ?
8551 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
8552 eCSR_DISCONNECT_REASON_DEAUTH;
8553 break;
8554 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
8555 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
8556 break;
8557 default:
8558 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
8559 break;
8560 }
8561 hddLog(LOG1,
8562 FL("convert to internal reason %d to reasonCode %d"),
8563 reason, reasonCode);
8564 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8565 pScanInfo = &pAdapter->scan_info;
8566 if (pScanInfo->mScanPending) {
8567 hddLog(LOG1,
8568 FL("Disconnect is in progress, Aborting Scan"));
8569 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
8570 eCSR_SCAN_ABORT_DEFAULT);
8571 }
8572#ifdef FEATURE_WLAN_TDLS
8573 /* First clean up the tdls peers if any */
8574 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
8575 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
8576 pAdapter->sessionId)
8577 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
8578 uint8_t *mac;
8579 mac =
8580 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
8581 hddLog(LOG1,
8582 "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d "
8583 MAC_ADDRESS_STR, __func__,
8584 pHddCtx->tdlsConnInfo[staIdx].staId,
8585 pAdapter->sessionId,
8586 MAC_ADDR_ARRAY(mac));
8587 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
8588 (pAdapter),
8589 pAdapter->sessionId, mac);
8590 }
8591 }
8592#endif
8593 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"),
8594 reasonCode);
8595 status = wlan_hdd_disconnect(pAdapter, reasonCode);
8596 if (0 != status) {
8597 hddLog(LOGE,
8598 FL("failure, returned %d"), status);
8599 return -EINVAL;
8600 }
8601 } else {
8602 hddLog(LOGE,
8603 FL("unexpected cfg disconnect called while in state (%d)"),
8604 pHddStaCtx->conn_info.connState);
8605 }
8606
8607 return status;
8608}
8609
8610/**
8611 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
8612 * @wiphy: Pointer to wiphy
8613 * @dev: Pointer to network device
8614 * @reason: Disconnect reason code
8615 *
8616 * Return: 0 for success, non-zero for failure
8617 */
8618static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
8619 struct net_device *dev, u16 reason)
8620{
8621 int ret;
8622 cds_ssr_protect(__func__);
8623 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
8624 cds_ssr_unprotect(__func__);
8625
8626 return ret;
8627}
8628
8629/**
8630 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
8631 * @pAdapter: Pointer to adapter
8632 * @param: Pointer to IBSS parameters
8633 *
8634 * This function is used to initialize the security settings in IBSS mode
8635 *
8636 * Return: 0 for success, non-zero for failure
8637 */
8638static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
8639 struct cfg80211_ibss_params
8640 *params)
8641{
8642 int status = 0;
8643 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8644 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
8645 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8646
8647 ENTER();
8648
8649 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
8650 cdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
8651 pHddStaCtx->ibss_enc_key_installed = 0;
8652
8653 if (params->ie_len && (NULL != params->ie)) {
8654 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
8655 params->ie_len, WLAN_EID_RSN)) {
8656 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
8657 encryptionType = eCSR_ENCRYPT_TYPE_AES;
8658 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
8659 tDot11fIEWPA dot11WPAIE;
8660 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
8661 u8 *ie;
8662
8663 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
8664 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
8665 params->ie_len,
8666 DOT11F_EID_WPA);
8667 if (NULL != ie) {
8668 pWextState->wpaVersion =
8669 IW_AUTH_WPA_VERSION_WPA;
8670 /* Unpack the WPA IE */
8671 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
8672 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
8673 &ie[2 + 4],
8674 ie[1] - 4, &dot11WPAIE);
8675 /*Extract the multicast cipher, the encType for unicast
8676 cipher for wpa-none is none */
8677 encryptionType =
8678 hdd_translate_wpa_to_csr_encryption_type
8679 (dot11WPAIE.multicast_cipher);
8680 }
8681 }
8682
8683 status =
8684 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
8685 params->ie_len);
8686
8687 if (0 > status) {
8688 hddLog(LOGE, FL("failed to parse WPA/RSN IE"));
8689 return status;
8690 }
8691 }
8692
8693 pWextState->roamProfile.AuthType.authType[0] =
8694 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8695
8696 if (params->privacy) {
8697 /* Security enabled IBSS, At this time there is no information
8698 * available about the security paramters, so initialise the
8699 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
8700 * The correct security parameters will be updated later in
8701 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
8702 * set inorder enable privacy bit in beacons
8703 */
8704
8705 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
8706 }
8707 hddLog(LOG2, FL("encryptionType=%d"), encryptionType);
8708 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
8709 pWextState->roamProfile.EncryptionType.numEntries = 1;
8710 pWextState->roamProfile.EncryptionType.encryptionType[0] =
8711 encryptionType;
8712 return status;
8713}
8714
8715/**
8716 * __wlan_hdd_cfg80211_join_ibss() - join ibss
8717 * @wiphy: Pointer to wiphy
8718 * @dev: Pointer to network device
8719 * @param: Pointer to IBSS join parameters
8720 *
8721 * This function is used to create/join an IBSS network
8722 *
8723 * Return: 0 for success, non-zero for failure
8724 */
8725static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
8726 struct net_device *dev,
8727 struct cfg80211_ibss_params *params)
8728{
8729 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8730 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8731 tCsrRoamProfile *pRoamProfile;
8732 int status;
8733 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8734 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8735 struct cdf_mac_addr bssid;
8736 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008737
8738 ENTER();
8739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008740 if (CDF_FTM_MODE == hdd_get_conparam()) {
8741 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8742 return -EINVAL;
8743 }
8744
8745 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
8746 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
8747 pAdapter->sessionId, pAdapter->device_mode));
8748 hddLog(LOG1, FL("Device_mode %s(%d)"),
8749 hdd_device_mode_to_string(pAdapter->device_mode),
8750 pAdapter->device_mode);
8751
8752 status = wlan_hdd_validate_context(pHddCtx);
8753
8754 if (0 != status) {
8755 hddLog(LOGE, FL("HDD context is not valid"));
8756 return status;
8757 }
8758
8759 if (NULL !=
8760#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
8761 params->chandef.chan)
8762#else
8763 params->channel)
8764#endif
8765 {
8766 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
8767 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8768 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8769 int indx;
8770
8771 /* Get channel number */
8772 channelNum = ieee80211_frequency_to_channel(
8773#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
8774 params->
8775 chandef.
8776 chan->
8777 center_freq);
8778#else
8779 params->
8780 channel->
8781 center_freq);
8782#endif
8783
8784 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
8785 validChan, &numChans)) {
8786 hddLog(LOGE, FL("No valid channel list"));
8787 return -EOPNOTSUPP;
8788 }
8789
8790 for (indx = 0; indx < numChans; indx++) {
8791 if (channelNum == validChan[indx]) {
8792 break;
8793 }
8794 }
8795 if (indx >= numChans) {
8796 hddLog(LOGE,
8797 FL("Not valid Channel %d"), channelNum);
8798 return -EINVAL;
8799 }
8800 }
8801
8802 if (!cds_allow_concurrency(pHddCtx, CDS_IBSS_MODE, channelNum,
8803 HW_MODE_20_MHZ)) {
8804 hdd_err("This concurrency combination is not allowed");
8805 return -ECONNREFUSED;
8806 }
8807 if (pHddCtx->config->policy_manager_enabled) {
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05308808 status = cdf_reset_connection_update();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008809 if (!CDF_IS_STATUS_SUCCESS(status))
8810 hdd_err("ERR: clear event failed");
8811
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05308812 status = cds_current_connections_update(pAdapter->sessionId,
8813 channelNum,
8814 CDS_UPDATE_REASON_JOIN_IBSS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008815 if (CDF_STATUS_E_FAILURE == status) {
8816 hdd_err("ERROR: connections update failed!!");
8817 return -EINVAL;
8818 }
8819
8820 if (CDF_STATUS_SUCCESS == status) {
Chandrasekaran, Manishekareceb8112015-11-16 15:38:53 +05308821 status = cdf_wait_for_connection_update();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008822 if (!CDF_IS_STATUS_SUCCESS(status)) {
8823 hdd_err("ERROR: cdf wait for event failed!!");
8824 return -EINVAL;
8825 }
8826 }
8827 }
8828
8829 /*Try disconnecting if already in connected state */
8830 status = wlan_hdd_try_disconnect(pAdapter);
8831 if (0 > status) {
8832 hddLog(LOGE,
8833 FL("Failed to disconnect the existing IBSS connection"));
8834 return -EALREADY;
8835 }
8836
8837 pRoamProfile = &pWextState->roamProfile;
8838
8839 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
8840 hddLog(LOGE,
8841 FL("Interface type is not set to IBSS"));
8842 return -EINVAL;
8843 }
8844
8845 /* enable selected protection checks in IBSS mode */
8846 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
8847
8848 if (CDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
8849 WNI_CFG_IBSS_ATIM_WIN_SIZE,
8850 pHddCtx->config->
8851 ibssATIMWinSize)) {
8852 hddLog(LOGE,
8853 FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"));
8854 }
8855
8856 /* BSSID is provided by upper layers hence no need to AUTO generate */
8857 if (NULL != params->bssid) {
8858 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
8859 == CDF_STATUS_E_FAILURE) {
8860 hddLog(LOGE,
8861 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
8862 return -EIO;
8863 }
8864 cdf_mem_copy(bssid.bytes, params->bssid, CDF_MAC_ADDR_SIZE);
8865 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
8866 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
8867 == CDF_STATUS_E_FAILURE) {
8868 hddLog(LOGE,
8869 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
8870 return -EIO;
8871 }
8872 cdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
8873 }
8874 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
8875 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
8876 pRoamProfile->beaconInterval = params->beacon_interval;
8877 else {
8878 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
8879 hddLog(LOG2,
8880 FL("input beacon interval %d TU is invalid, use default %d TU"),
8881 params->beacon_interval, pRoamProfile->beaconInterval);
8882 }
8883
8884 /* Set Channel */
8885 if (channelNum) {
8886 /* Set the Operational Channel */
8887 hddLog(LOG2, FL("set channel %d"), channelNum);
8888 pRoamProfile->ChannelInfo.numOfChannels = 1;
8889 pHddStaCtx->conn_info.operationChannel = channelNum;
8890 pRoamProfile->ChannelInfo.ChannelList =
8891 &pHddStaCtx->conn_info.operationChannel;
8892 }
8893
8894 /* Initialize security parameters */
8895 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
8896 if (status < 0) {
8897 hddLog(LOGE,
8898 FL("failed to set security parameters"));
8899 return status;
8900 }
8901
8902 /* Issue connect start */
8903 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
8904 params->ssid_len,
8905 bssid.bytes,
8906 NULL,
8907 pHddStaCtx->conn_info.
8908 operationChannel);
8909
8910 if (0 > status) {
8911 hddLog(LOGE, FL("connect failed"));
8912 return status;
8913 }
8914
8915 return 0;
8916}
8917
8918/**
8919 * wlan_hdd_cfg80211_join_ibss() - join ibss
8920 * @wiphy: Pointer to wiphy
8921 * @dev: Pointer to network device
8922 * @param: Pointer to IBSS join parameters
8923 *
8924 * This function is used to create/join an IBSS network
8925 *
8926 * Return: 0 for success, non-zero for failure
8927 */
8928static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
8929 struct net_device *dev,
8930 struct cfg80211_ibss_params *params)
8931{
8932 int ret = 0;
8933
8934 cds_ssr_protect(__func__);
8935 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
8936 cds_ssr_unprotect(__func__);
8937
8938 return ret;
8939}
8940
8941/**
8942 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
8943 * @wiphy: Pointer to wiphy
8944 * @dev: Pointer to network device
8945 *
8946 * This function is used to leave an IBSS network
8947 *
8948 * Return: 0 for success, non-zero for failure
8949 */
8950static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
8951 struct net_device *dev)
8952{
8953 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8954 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8955 tCsrRoamProfile *pRoamProfile;
8956 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8957 int status;
8958 CDF_STATUS hal_status;
8959
8960 ENTER();
8961
8962 if (CDF_FTM_MODE == hdd_get_conparam()) {
8963 hddLog(LOGE, FL("Command not allowed in FTM mode"));
8964 return -EINVAL;
8965 }
8966
8967 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
8968 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
8969 pAdapter->sessionId,
8970 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
8971 status = wlan_hdd_validate_context(pHddCtx);
8972 if (0 != status) {
8973 hddLog(LOGE, FL("HDD context is not valid"));
8974 return status;
8975 }
8976
8977 hddLog(LOG1, FL("Device_mode %s(%d)"),
8978 hdd_device_mode_to_string(pAdapter->device_mode),
8979 pAdapter->device_mode);
8980 if (NULL == pWextState) {
8981 hddLog(LOGE, FL("Data Storage Corruption"));
8982 return -EIO;
8983 }
8984
8985 pRoamProfile = &pWextState->roamProfile;
8986
8987 /* Issue disconnect only if interface type is set to IBSS */
8988 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
8989 hddLog(LOGE,
8990 FL("BSS Type is not set to IBSS"));
8991 return -EINVAL;
8992 }
8993
8994 /* Issue Disconnect request */
8995 INIT_COMPLETION(pAdapter->disconnect_comp_var);
8996 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8997 pAdapter->sessionId,
8998 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
8999 if (!CDF_IS_STATUS_SUCCESS(hal_status)) {
9000 hddLog(LOGE,
9001 FL("sme_roam_disconnect failed hal_status(%d)"),
9002 hal_status);
9003 return -EAGAIN;
9004 }
9005
9006 return 0;
9007}
9008
9009/**
9010 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
9011 * @wiphy: Pointer to wiphy
9012 * @dev: Pointer to network device
9013 *
9014 * This function is used to leave an IBSS network
9015 *
9016 * Return: 0 for success, non-zero for failure
9017 */
9018static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
9019 struct net_device *dev)
9020{
9021 int ret = 0;
9022
9023 cds_ssr_protect(__func__);
9024 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
9025 cds_ssr_unprotect(__func__);
9026
9027 return ret;
9028}
9029
9030/**
9031 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9032 * @wiphy: Pointer to wiphy
9033 * @changed: Parameters changed
9034 *
9035 * This function is used to set the phy parameters. RTS Threshold/FRAG
9036 * Threshold/Retry Count etc.
9037 *
9038 * Return: 0 for success, non-zero for failure
9039 */
9040static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
9041 u32 changed)
9042{
9043 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9044 tHalHandle hHal = pHddCtx->hHal;
9045 int status;
9046
9047 ENTER();
9048
9049 if (CDF_FTM_MODE == hdd_get_conparam()) {
9050 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9051 return -EINVAL;
9052 }
9053
9054 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
9055 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
9056 NO_SESSION, wiphy->rts_threshold));
9057 status = wlan_hdd_validate_context(pHddCtx);
9058
9059 if (0 != status) {
9060 hddLog(LOGE,
9061 FL("HDD context is not valid"));
9062 return status;
9063 }
9064
9065 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
9066 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
9067 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
9068
9069 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
9070 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
9071 hddLog(LOGE,
9072 FL("Invalid RTS Threshold value %u"),
9073 rts_threshold);
9074 return -EINVAL;
9075 }
9076
9077 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
9078 rts_threshold)) {
9079 hddLog(LOGE,
9080 FL("sme_cfg_set_int failed for rts_threshold value %u"),
9081 rts_threshold);
9082 return -EIO;
9083 }
9084
9085 hddLog(LOG2, FL("set rts threshold %u"), rts_threshold);
9086 }
9087
9088 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
9089 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
9090 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
9091 wiphy->frag_threshold;
9092
9093 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
9094 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
9095 hddLog(LOGE,
9096 FL("Invalid frag_threshold value %hu"),
9097 frag_threshold);
9098 return -EINVAL;
9099 }
9100
9101 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
9102 frag_threshold)) {
9103 hddLog(LOGE,
9104 FL("sme_cfg_set_int failed for frag_threshold value %hu"),
9105 frag_threshold);
9106 return -EIO;
9107 }
9108
9109 hddLog(LOG2, FL("set frag threshold %hu"), frag_threshold);
9110 }
9111
9112 if ((changed & WIPHY_PARAM_RETRY_SHORT)
9113 || (changed & WIPHY_PARAM_RETRY_LONG)) {
9114 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
9115 wiphy->retry_short : wiphy->retry_long;
9116
9117 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
9118 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
9119 hddLog(LOGE,
9120 FL("Invalid Retry count %hu"), retry_value);
9121 return -EINVAL;
9122 }
9123
9124 if (changed & WIPHY_PARAM_RETRY_SHORT) {
9125 if (0 != sme_cfg_set_int(hHal,
9126 WNI_CFG_LONG_RETRY_LIMIT,
9127 retry_value)) {
9128 hddLog(LOGE,
9129 FL("sme_cfg_set_int failed for long retry count %hu"),
9130 retry_value);
9131 return -EIO;
9132 }
9133 hddLog(LOG2,
9134 FL("set long retry count %hu"), retry_value);
9135 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
9136 if (0 != sme_cfg_set_int(hHal,
9137 WNI_CFG_SHORT_RETRY_LIMIT,
9138 retry_value)) {
9139 hddLog(LOGE,
9140 FL("sme_cfg_set_int failed for short retry count %hu"),
9141 retry_value);
9142 return -EIO;
9143 }
9144 hddLog(LOG2,
9145 FL("set short retry count %hu"), retry_value);
9146 }
9147 }
9148
9149 return 0;
9150}
9151
9152/**
9153 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
9154 * @wiphy: Pointer to wiphy
9155 * @changed: Parameters changed
9156 *
9157 * Return: 0 for success, non-zero for failure
9158 */
9159static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
9160{
9161 int ret;
9162
9163 cds_ssr_protect(__func__);
9164 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
9165 cds_ssr_unprotect(__func__);
9166
9167 return ret;
9168}
9169
9170/**
9171 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
9172 * key
9173 * @wiphy: Pointer to wiphy
9174 * @dev: Pointer to network device
9175 * @key_index: Key index
9176 *
9177 * Return: 0
9178 */
9179static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9180 struct net_device *netdev,
9181 u8 key_index)
9182{
9183 ENTER();
9184 return 0;
9185}
9186
9187/**
9188 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
9189 * wlan_hdd_set_default_mgmt_key
9190 * @wiphy: pointer to wiphy
9191 * @netdev: pointer to net_device structure
9192 * @key_index: key index
9193 *
9194 * Return: 0 on success, error number on failure
9195 */
9196static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
9197 struct net_device *netdev,
9198 u8 key_index)
9199{
9200 int ret;
9201
9202 cds_ssr_protect(__func__);
9203 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
9204 cds_ssr_unprotect(__func__);
9205
9206 return ret;
9207}
9208
9209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9210/**
9211 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
9212 * @wiphy: Pointer to wiphy
9213 * @dev: Pointer to network device
9214 * @params: Pointer to tx queue parameters
9215 *
9216 * Return: 0
9217 */
9218static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
9219 struct net_device *dev,
9220 struct ieee80211_txq_params *params)
9221{
9222 ENTER();
9223 return 0;
9224}
9225#else
9226/**
9227 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
9228 * @wiphy: Pointer to wiphy
9229 * @params: Pointer to tx queue parameters
9230 *
9231 * Return: 0
9232 */
9233static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
9234 struct ieee80211_txq_params *params)
9235{
9236 ENTER();
9237 return 0;
9238}
9239#endif /* LINUX_VERSION_CODE */
9240
9241/**
9242 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
9243 * @wiphy: pointer to wiphy
9244 * @netdev: pointer to net_device structure
9245 * @params: pointer to ieee80211_txq_params
9246 *
9247 * Return: 0 on success, error number on failure
9248 */
9249#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WITH_BACKPORTS)
9250static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
9251 struct net_device *dev,
9252 struct ieee80211_txq_params *params)
9253{
9254 int ret;
9255
9256 cds_ssr_protect(__func__);
9257 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
9258 cds_ssr_unprotect(__func__);
9259
9260 return ret;
9261}
9262#else
9263static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
9264 struct ieee80211_txq_params *params)
9265{
9266 int ret;
9267
9268 cds_ssr_protect(__func__);
9269 ret = __wlan_hdd_set_txq_params(wiphy, params);
9270 cds_ssr_unprotect(__func__);
9271
9272 return ret;
9273}
9274#endif /* LINUX_VERSION_CODE */
9275
9276/**
9277 * __wlan_hdd_cfg80211_del_station() - delete station v2
9278 * @wiphy: Pointer to wiphy
9279 * @param: Pointer to delete station parameter
9280 *
9281 * Return: 0 for success, non-zero for failure
9282 */
9283static
9284int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9285 struct net_device *dev,
9286 struct tagCsrDelStaParams *pDelStaParams)
9287{
9288 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9289 hdd_context_t *pHddCtx;
9290 CDF_STATUS cdf_status = CDF_STATUS_E_FAILURE;
9291 hdd_hostapd_state_t *hapd_state;
9292 int status;
9293 uint8_t staId;
9294 uint8_t *mac;
9295
9296 ENTER();
9297
9298 if (CDF_FTM_MODE == hdd_get_conparam()) {
9299 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9300 return -EINVAL;
9301 }
9302
9303 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
9304 TRACE_CODE_HDD_CFG80211_DEL_STA,
9305 pAdapter->sessionId, pAdapter->device_mode));
9306
9307 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9308 status = wlan_hdd_validate_context(pHddCtx);
9309
9310 if (0 != status) {
9311 hddLog(LOGE, FL("HDD context is not valid"));
9312 return status;
9313 }
9314
9315 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
9316
9317 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
9318 (WLAN_HDD_P2P_GO == pAdapter->device_mode)) {
9319
9320 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9321 if (!hapd_state) {
9322 hddLog(LOGE, "%s: Hostapd State is Null", __func__);
9323 return 0;
9324 }
9325
9326 if (cdf_is_macaddr_broadcast((struct cdf_mac_addr *) mac)) {
9327 uint16_t i;
9328 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
9329 if ((pAdapter->aStaInfo[i].isUsed) &&
9330 (!pAdapter->aStaInfo[i].
9331 isDeauthInProgress)) {
9332 cdf_mem_copy(
9333 mac,
9334 pAdapter->aStaInfo[i].
9335 macAddrSTA.bytes,
9336 ETHER_ADDR_LEN);
9337 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
9338 hdd_ipa_wlan_evt(pAdapter,
9339 pAdapter->
9340 aStaInfo[i].
9341 ucSTAId,
9342 WLAN_CLIENT_DISCONNECT,
9343 mac);
9344 }
9345 hddLog(LOG1,
9346 FL("Delete STA with MAC::"
9347 MAC_ADDRESS_STR),
9348 MAC_ADDR_ARRAY(mac));
9349
9350 if (pHddCtx->dev_dfs_cac_status ==
9351 DFS_CAC_IN_PROGRESS)
9352 goto fn_end;
9353
9354 cdf_event_reset(&hapd_state->cdf_event);
9355 hdd_softap_sta_disassoc(pAdapter,
9356 mac);
9357 cdf_status =
9358 hdd_softap_sta_deauth(pAdapter,
9359 pDelStaParams);
9360 if (CDF_IS_STATUS_SUCCESS(cdf_status)) {
9361 pAdapter->aStaInfo[i].
9362 isDeauthInProgress = true;
9363 cdf_status =
9364 cdf_wait_single_event(
9365 &hapd_state->cdf_event,
9366 1000);
9367 if (!CDF_IS_STATUS_SUCCESS(
9368 cdf_status))
9369 hddLog(LOGE,
9370 "%s: Deauth wait time expired",
9371 __func__);
9372 }
9373 }
9374 }
9375 } else {
9376 cdf_status =
9377 hdd_softap_get_sta_id(pAdapter,
9378 (struct cdf_mac_addr *) mac,
9379 &staId);
9380 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
9381 hddLog(LOG1,
9382 FL("Skip DEL STA as this is not used::"
9383 MAC_ADDRESS_STR),
9384 MAC_ADDR_ARRAY(mac));
9385 return -ENOENT;
9386 }
9387
9388 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
9389 hdd_ipa_wlan_evt(pAdapter, staId,
9390 WLAN_CLIENT_DISCONNECT, mac);
9391 }
9392
9393 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
9394 true) {
9395 hddLog(LOG1,
9396 FL("Skip DEL STA as deauth is in progress::"
9397 MAC_ADDRESS_STR),
9398 MAC_ADDR_ARRAY(mac));
9399 return -ENOENT;
9400 }
9401
9402 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
9403
9404 hddLog(LOG1,
9405 FL("Delete STA with MAC::" MAC_ADDRESS_STR),
9406 MAC_ADDR_ARRAY(mac));
9407
9408 /* Case: SAP in ACS selected DFS ch and client connected
9409 * Now Radar detected. Then if random channel is another
9410 * DFS ch then new CAC is initiated and no TX allowed.
9411 * So do not send any mgmt frames as it will timeout
9412 * during CAC.
9413 */
9414
9415 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
9416 goto fn_end;
9417
9418 cdf_event_reset(&hapd_state->cdf_event);
9419 hdd_softap_sta_disassoc(pAdapter, mac);
9420 cdf_status = hdd_softap_sta_deauth(pAdapter,
9421 pDelStaParams);
9422 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
9423 pAdapter->aStaInfo[staId].isDeauthInProgress =
9424 false;
9425 hddLog(LOG1,
9426 FL("STA removal failed for ::"
9427 MAC_ADDRESS_STR),
9428 MAC_ADDR_ARRAY(mac));
9429 return -ENOENT;
9430 } else {
9431 cdf_status = cdf_wait_single_event(
9432 &hapd_state->cdf_event,
9433 1000);
9434 if (!CDF_IS_STATUS_SUCCESS(cdf_status))
9435 hddLog(LOGE,
9436 "%s: Deauth wait time expired",
9437 __func__);
9438 }
9439 }
9440 }
9441
9442fn_end:
9443 EXIT();
9444 return 0;
9445}
9446
9447#ifdef CFG80211_DEL_STA_V2
9448/**
9449 * wlan_hdd_cfg80211_del_station() - delete station v2
9450 * @wiphy: Pointer to wiphy
9451 * @param: Pointer to delete station parameter
9452 *
9453 * Return: 0 for success, non-zero for failure
9454 */
9455int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9456 struct net_device *dev,
9457 struct station_del_parameters *param)
9458#else
9459/**
9460 * wlan_hdd_cfg80211_del_station() - delete station
9461 * @wiphy: Pointer to wiphy
9462 * @mac: Pointer to station mac address
9463 *
9464 * Return: 0 for success, non-zero for failure
9465 */
9466#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9467int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9468 struct net_device *dev,
9469 const uint8_t *mac)
9470#else
9471int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
9472 struct net_device *dev,
9473 uint8_t *mac)
9474#endif
9475#endif
9476{
9477 int ret;
9478 struct tagCsrDelStaParams delStaParams;
9479
9480 cds_ssr_protect(__func__);
9481#ifdef CFG80211_DEL_STA_V2
9482 if (NULL == param) {
9483 hddLog(LOGE, FL("Invalid argumet passed"));
9484 return -EINVAL;
9485 }
9486 wlansap_populate_del_sta_params(param->mac, param->reason_code,
9487 param->subtype, &delStaParams);
9488#else
9489 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
9490 (SIR_MAC_MGMT_DEAUTH >> 4),
9491 &delStaParams);
9492#endif
9493 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
9494 cds_ssr_unprotect(__func__);
9495
9496 return ret;
9497}
9498
9499/**
9500 * __wlan_hdd_cfg80211_add_station() - add station
9501 * @wiphy: Pointer to wiphy
9502 * @mac: Pointer to station mac address
9503 * @pmksa: Pointer to add station parameter
9504 *
9505 * Return: 0 for success, non-zero for failure
9506 */
9507static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
9508 struct net_device *dev,
9509 const uint8_t *mac,
9510 struct station_parameters *params)
9511{
9512 int status = -EPERM;
9513#ifdef FEATURE_WLAN_TDLS
9514 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9515 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9516 u32 mask, set;
9517
9518 ENTER();
9519
9520 if (CDF_FTM_MODE == hdd_get_conparam()) {
9521 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9522 return -EINVAL;
9523 }
9524
9525 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
9526 TRACE_CODE_HDD_CFG80211_ADD_STA,
9527 pAdapter->sessionId, params->listen_interval));
9528
9529 if (0 != wlan_hdd_validate_context(pHddCtx)) {
9530 hddLog(LOGE, FL("HDD context is not valid"));
9531 return -EINVAL;
9532 }
9533
9534 mask = params->sta_flags_mask;
9535
9536 set = params->sta_flags_set;
9537
9538 hddLog(LOG1, FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), mask, set,
9539 MAC_ADDR_ARRAY(mac));
9540
9541 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
9542 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
9543 status =
9544 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
9545 }
9546 }
9547#endif
9548 return status;
9549}
9550
9551/**
9552 * wlan_hdd_cfg80211_add_station() - add station
9553 * @wiphy: Pointer to wiphy
9554 * @mac: Pointer to station mac address
9555 * @pmksa: Pointer to add station parameter
9556 *
9557 * Return: 0 for success, non-zero for failure
9558 */
9559#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9560static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
9561 struct net_device *dev,
9562 const uint8_t *mac,
9563 struct station_parameters *params)
9564#else
9565static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
9566 struct net_device *dev, uint8_t *mac,
9567 struct station_parameters *params)
9568#endif
9569{
9570 int ret;
9571
9572 cds_ssr_protect(__func__);
9573 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
9574 cds_ssr_unprotect(__func__);
9575
9576 return ret;
9577}
9578
9579#ifdef FEATURE_WLAN_LFR
9580/**
9581 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
9582 * @wiphy: Pointer to wiphy
9583 * @dev: Pointer to network device
9584 * @pmksa: Pointer to set pmksa parameter
9585 *
9586 * Return: 0 for success, non-zero for failure
9587 */
9588static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
9589 struct net_device *dev,
9590 struct cfg80211_pmksa *pmksa)
9591{
9592 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9593 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9594 tHalHandle halHandle;
9595 CDF_STATUS result = CDF_STATUS_SUCCESS;
9596 int status;
9597 tPmkidCacheInfo pmk_id;
9598
9599 if (CDF_FTM_MODE == hdd_get_conparam()) {
9600 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9601 return -EINVAL;
9602 }
9603
9604 if (!pmksa) {
9605 hddLog(LOGE, FL("pmksa is NULL"));
9606 return -EINVAL;
9607 }
9608
9609 if (!pmksa->bssid || !pmksa->pmkid) {
9610 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
9611 pmksa->bssid, pmksa->pmkid);
9612 return -EINVAL;
9613 }
9614
9615 hddLog(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR),
9616 MAC_ADDR_ARRAY(pmksa->bssid));
9617
9618 status = wlan_hdd_validate_context(pHddCtx);
9619
9620 if (0 != status) {
9621 hddLog(LOGE, FL("HDD context is not valid"));
9622 return status;
9623 }
9624
9625 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9626
9627 cdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, ETHER_ADDR_LEN);
9628 cdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
9629
9630 /* Add to the PMKSA ID Cache in CSR */
9631 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
9632 &pmk_id, 1, false);
9633
9634 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
9635 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
9636 pAdapter->sessionId, result));
9637
9638 return CDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
9639}
9640
9641/**
9642 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
9643 * @wiphy: Pointer to wiphy
9644 * @dev: Pointer to network device
9645 * @pmksa: Pointer to set pmksa parameter
9646 *
9647 * Return: 0 for success, non-zero for failure
9648 */
9649static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
9650 struct net_device *dev,
9651 struct cfg80211_pmksa *pmksa)
9652{
9653 int ret;
9654
9655 cds_ssr_protect(__func__);
9656 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
9657 cds_ssr_unprotect(__func__);
9658
9659 return ret;
9660}
9661
9662/**
9663 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
9664 * @wiphy: Pointer to wiphy
9665 * @dev: Pointer to network device
9666 * @pmksa: Pointer to pmksa parameter
9667 *
9668 * Return: 0 for success, non-zero for failure
9669 */
9670static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
9671 struct net_device *dev,
9672 struct cfg80211_pmksa *pmksa)
9673{
9674 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9675 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9676 tHalHandle halHandle;
9677 int status = 0;
9678
9679 if (CDF_FTM_MODE == hdd_get_conparam()) {
9680 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9681 return -EINVAL;
9682 }
9683
9684 if (!pmksa) {
9685 hddLog(LOGE, FL("pmksa is NULL"));
9686 return -EINVAL;
9687 }
9688
9689 if (!pmksa->bssid) {
9690 hddLog(LOGE, FL("pmksa->bssid is NULL"));
9691 return -EINVAL;
9692 }
9693
9694 hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR),
9695 MAC_ADDR_ARRAY(pmksa->bssid));
9696
9697 status = wlan_hdd_validate_context(pHddCtx);
9698
9699 if (0 != status) {
9700 hddLog(LOGE, FL("HDD context is not valid"));
9701 return status;
9702 }
9703
9704 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9705
9706 /* Delete the PMKID CSR cache */
9707 if (CDF_STATUS_SUCCESS !=
9708 sme_roam_del_pmkid_from_cache(halHandle,
9709 pAdapter->sessionId, pmksa->bssid,
9710 false)) {
9711 hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR),
9712 MAC_ADDR_ARRAY(pmksa->bssid));
9713 status = -EINVAL;
9714 }
9715
9716 return status;
9717}
9718
9719/**
9720 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
9721 * @wiphy: Pointer to wiphy
9722 * @dev: Pointer to network device
9723 * @pmksa: Pointer to pmksa parameter
9724 *
9725 * Return: 0 for success, non-zero for failure
9726 */
9727static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
9728 struct net_device *dev,
9729 struct cfg80211_pmksa *pmksa)
9730{
9731 int ret;
9732
9733 cds_ssr_protect(__func__);
9734 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
9735 cds_ssr_unprotect(__func__);
9736
9737 return ret;
9738
9739}
9740
9741/**
9742 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
9743 * @wiphy: Pointer to wiphy
9744 * @dev: Pointer to network device
9745 *
9746 * Return: 0 for success, non-zero for failure
9747 */
9748static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
9749 struct net_device *dev)
9750{
9751 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9752 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9753 tHalHandle halHandle;
9754 int status = 0;
9755
9756 if (CDF_FTM_MODE == hdd_get_conparam()) {
9757 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9758 return -EINVAL;
9759 }
9760
9761 hddLog(LOGW, FL("Flushing PMKSA"));
9762
9763 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9764 status = wlan_hdd_validate_context(pHddCtx);
9765
9766 if (0 != status) {
9767 hddLog(LOGE, FL("HDD context is not valid"));
9768 return status;
9769 }
9770
9771 /* Retrieve halHandle */
9772 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
9773
9774 /* Flush the PMKID cache in CSR */
9775 if (CDF_STATUS_SUCCESS !=
9776 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
9777 true)) {
9778 hddLog(LOGE, FL("Cannot flush PMKIDCache"));
9779 status = -EINVAL;
9780 }
9781
9782 return status;
9783}
9784
9785/**
9786 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
9787 * @wiphy: Pointer to wiphy
9788 * @dev: Pointer to network device
9789 *
9790 * Return: 0 for success, non-zero for failure
9791 */
9792static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
9793 struct net_device *dev)
9794{
9795 int ret;
9796
9797 cds_ssr_protect(__func__);
9798 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
9799 cds_ssr_unprotect(__func__);
9800
9801 return ret;
9802}
9803#endif
9804
9805#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
9806/**
9807 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
9808 * @wiphy: Pointer to wiphy
9809 * @dev: Pointer to network device
9810 * @ftie: Pointer to fast transition ie parameter
9811 *
9812 * Return: 0 for success, non-zero for failure
9813 */
9814static int
9815__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
9816 struct net_device *dev,
9817 struct cfg80211_update_ft_ies_params *ftie)
9818{
9819 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9820 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9821 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9822 int status;
9823
9824 status = wlan_hdd_validate_context(hdd_ctx);
9825 if (status)
9826 return status;
9827
9828 if (CDF_FTM_MODE == hdd_get_conparam()) {
9829 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9830 return -EINVAL;
9831 }
9832
9833 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
9834 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
9835 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
9836 /* Added for debug on reception of Re-assoc Req. */
9837 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
9838 hddLog(LOGE,
9839 FL("Called with Ie of length = %zu when not associated"),
9840 ftie->ie_len);
9841 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
9842 }
9843#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
9844 hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__,
9845 ftie->ie_len);
9846#endif
9847
9848 /* Pass the received FT IEs to SME */
9849 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
9850 (const u8 *)ftie->ie, ftie->ie_len);
9851 return 0;
9852}
9853
9854/**
9855 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
9856 * @wiphy: Pointer to wiphy
9857 * @dev: Pointer to network device
9858 * @ftie: Pointer to fast transition ie parameter
9859 *
9860 * Return: 0 for success, non-zero for failure
9861 */
9862static int
9863wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
9864 struct net_device *dev,
9865 struct cfg80211_update_ft_ies_params *ftie)
9866{
9867 int ret;
9868
9869 cds_ssr_protect(__func__);
9870 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
9871 cds_ssr_unprotect(__func__);
9872
9873 return ret;
9874}
9875#endif
9876
9877#ifdef WLAN_FEATURE_GTK_OFFLOAD
9878/**
9879 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
9880 * @callbackContext: Callback context
9881 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
9882 *
9883 * Callback rountine called upon receiving response for get offload info
9884 *
9885 * Return: none
9886 */
9887void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
9888 tpSirGtkOffloadGetInfoRspParams
9889 pGtkOffloadGetInfoRsp)
9890{
9891 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
9892 uint8_t tempReplayCounter[8];
9893 hdd_station_ctx_t *pHddStaCtx;
9894
9895 ENTER();
9896
9897 if (NULL == pAdapter) {
9898 hddLog(LOGE, FL("HDD adapter is Null"));
9899 return;
9900 }
9901
9902 if (NULL == pGtkOffloadGetInfoRsp) {
9903 hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null"));
9904 return;
9905 }
9906
9907 if (CDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
9908 hddLog(LOGE, FL("wlan Failed to get replay counter value"));
9909 return;
9910 }
9911
9912 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9913 /* Update replay counter */
9914 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
9915 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
9916
9917 {
9918 /* changing from little to big endian since supplicant
9919 * works on big endian format
9920 */
9921 int i;
9922 uint8_t *p =
9923 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
9924
9925 for (i = 0; i < 8; i++) {
9926 tempReplayCounter[7 - i] = (uint8_t) p[i];
9927 }
9928 }
9929
9930 /* Update replay counter to NL */
9931 cfg80211_gtk_rekey_notify(pAdapter->dev, pGtkOffloadGetInfoRsp->bssId,
9932 tempReplayCounter, GFP_KERNEL);
9933}
9934
9935/**
9936 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
9937 * @wiphy: Pointer to wiphy
9938 * @dev: Pointer to network device
9939 * @data: Pointer to rekey data
9940 *
9941 * This function is used to offload GTK rekeying job to the firmware.
9942 *
9943 * Return: 0 for success, non-zero for failure
9944 */
9945int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
9946 struct net_device *dev,
9947 struct cfg80211_gtk_rekey_data *data)
9948{
9949 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9950 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9951 hdd_station_ctx_t *pHddStaCtx;
9952 tHalHandle hHal;
9953 int result;
9954 tSirGtkOffloadParams hddGtkOffloadReqParams;
9955 CDF_STATUS status = CDF_STATUS_E_FAILURE;
9956
9957 ENTER();
9958
9959 if (CDF_FTM_MODE == hdd_get_conparam()) {
9960 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9961 return -EINVAL;
9962 }
9963
9964 MTRACE(cdf_trace(CDF_MODULE_ID_HDD,
9965 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
9966 pAdapter->sessionId, pAdapter->device_mode));
9967
9968 result = wlan_hdd_validate_context(pHddCtx);
9969
9970 if (0 != result) {
9971 hddLog(LOGE, FL("HDD context is not valid"));
9972 return result;
9973 }
9974
9975 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9976 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9977 if (NULL == hHal) {
9978 hddLog(LOGE, FL("HAL context is Null!!!"));
9979 return -EAGAIN;
9980 }
9981
9982 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
9983 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
9984 NL80211_KCK_LEN);
9985 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
9986 NL80211_KEK_LEN);
9987 memcpy(pHddStaCtx->gtkOffloadReqParams.bssId,
9988 &pHddStaCtx->conn_info.bssId, CDF_MAC_ADDR_SIZE);
9989 {
9990 /* changing from big to little endian since driver
9991 * works on little endian format
9992 */
9993 uint8_t *p =
9994 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
9995 ullKeyReplayCounter;
9996 int i;
9997
9998 for (i = 0; i < 8; i++) {
9999 p[7 - i] = data->replay_ctr[i];
10000 }
10001 }
10002
10003 if (true == pHddCtx->hdd_wlan_suspended) {
10004 /* if wlan is suspended, enable GTK offload directly from here */
10005 memcpy(&hddGtkOffloadReqParams,
10006 &pHddStaCtx->gtkOffloadReqParams,
10007 sizeof(tSirGtkOffloadParams));
10008 status =
10009 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
10010 pAdapter->sessionId);
10011
10012 if (CDF_STATUS_SUCCESS != status) {
10013 hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"),
10014 status);
10015 return -EINVAL;
10016 }
10017 hddLog(LOG1, FL("sme_set_gtk_offload successful"));
10018 } else {
10019 hddLog(LOG1,
10020 FL("wlan not suspended GTKOffload request is stored"));
10021 }
10022
10023 return result;
10024}
10025
10026/**
10027 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
10028 * @wiphy: Pointer to wiphy
10029 * @dev: Pointer to network device
10030 * @data: Pointer to rekey data
10031 *
10032 * This function is used to offload GTK rekeying job to the firmware.
10033 *
10034 * Return: 0 for success, non-zero for failure
10035 */
10036int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
10037 struct net_device *dev,
10038 struct cfg80211_gtk_rekey_data *data)
10039{
10040 int ret;
10041
10042 cds_ssr_protect(__func__);
10043 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
10044 cds_ssr_unprotect(__func__);
10045
10046 return ret;
10047}
10048#endif /*WLAN_FEATURE_GTK_OFFLOAD */
10049
10050/**
10051 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
10052 * @wiphy: Pointer to wiphy
10053 * @dev: Pointer to network device
10054 * @param: Pointer to access control parameter
10055 *
10056 * Return: 0 for success, non-zero for failure
10057 */
10058static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10059 struct net_device *dev,
10060 const struct cfg80211_acl_data *params)
10061{
10062 int i;
10063 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10064 hdd_hostapd_state_t *pHostapdState;
10065 tsap_Config_t *pConfig;
10066 v_CONTEXT_t p_cds_context = NULL;
10067 hdd_context_t *pHddCtx;
10068 int status;
10069 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
10070
10071 ENTER();
10072
10073 if (CDF_FTM_MODE == hdd_get_conparam()) {
10074 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10075 return -EINVAL;
10076 }
10077
10078 if (NULL == params) {
10079 hddLog(LOGE, FL("params is Null"));
10080 return -EINVAL;
10081 }
10082
10083 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10084 status = wlan_hdd_validate_context(pHddCtx);
10085
10086 if (0 != status) {
10087 hddLog(LOGE, FL("HDD context is not valid"));
10088 return status;
10089 }
10090
10091 p_cds_context = pHddCtx->pcds_context;
10092 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10093
10094 if (NULL == pHostapdState) {
10095 hddLog(LOGE, FL("pHostapdState is Null"));
10096 return -EINVAL;
10097 }
10098
10099 hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy,
10100 params->n_acl_entries);
10101
10102 if (WLAN_HDD_SOFTAP == pAdapter->device_mode) {
10103 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
10104
10105 /* default value */
10106 pConfig->num_accept_mac = 0;
10107 pConfig->num_deny_mac = 0;
10108
10109 /**
10110 * access control policy
10111 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
10112 * listed in hostapd.deny file.
10113 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
10114 * listed in hostapd.accept file.
10115 */
10116 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
10117 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
10118 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
10119 params->acl_policy) {
10120 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
10121 } else {
10122 hddLog(LOGE, FL("Acl Policy : %d is not supported"),
10123 params->acl_policy);
10124 return -ENOTSUPP;
10125 }
10126
10127 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
10128 pConfig->num_accept_mac = params->n_acl_entries;
10129 for (i = 0; i < params->n_acl_entries; i++) {
10130 hddLog(LOG1,
10131 FL("** Add ACL MAC entry %i in WhiletList :"
10132 MAC_ADDRESS_STR), i,
10133 MAC_ADDR_ARRAY(
10134 params->mac_addrs[i].addr));
10135
10136 cdf_mem_copy(&pConfig->accept_mac[i],
10137 params->mac_addrs[i].addr,
10138 sizeof(qcmacaddr));
10139 }
10140 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
10141 pConfig->num_deny_mac = params->n_acl_entries;
10142 for (i = 0; i < params->n_acl_entries; i++) {
10143 hddLog(LOG1,
10144 FL("** Add ACL MAC entry %i in BlackList :"
10145 MAC_ADDRESS_STR), i,
10146 MAC_ADDR_ARRAY(
10147 params->mac_addrs[i].addr));
10148
10149 cdf_mem_copy(&pConfig->deny_mac[i],
10150 params->mac_addrs[i].addr,
10151 sizeof(qcmacaddr));
10152 }
10153 }
10154#ifdef WLAN_FEATURE_MBSSID
10155 cdf_status =
10156 wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
10157 pConfig);
10158#else
10159 cdf_status = wlansap_set_mac_acl(p_cds_context, pConfig);
10160#endif
10161 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
10162 hddLog(LOGE, FL("SAP Set Mac Acl fail"));
10163 return -EINVAL;
10164 }
10165 } else {
10166 hddLog(LOG1, FL("Invalid device_mode %s(%d)"),
10167 hdd_device_mode_to_string(pAdapter->device_mode),
10168 pAdapter->device_mode);
10169 return -EINVAL;
10170 }
10171
10172 return 0;
10173}
10174
10175/**
10176 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
10177 * __wlan_hdd_cfg80211_set_mac_acl
10178 * @wiphy: pointer to wiphy structure
10179 * @dev: pointer to net_device
10180 * @params: pointer to cfg80211_acl_data
10181 *
10182 * Return; 0 on success, error number otherwise
10183 */
10184static int
10185wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
10186 struct net_device *dev,
10187 const struct cfg80211_acl_data *params)
10188{
10189 int ret;
10190
10191 cds_ssr_protect(__func__);
10192 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
10193 cds_ssr_unprotect(__func__);
10194
10195 return ret;
10196}
10197
10198#ifdef WLAN_NL80211_TESTMODE
10199#ifdef FEATURE_WLAN_LPHB
10200/**
10201 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
10202 * @pHddCtx: Pointer to hdd context
10203 * @lphbInd: Pointer to low power heart beat indication parameter
10204 *
10205 * Return: none
10206 */
10207void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
10208{
10209 struct sk_buff *skb;
10210
10211 hddLog(LOGE, FL("LPHB indication arrived"));
10212
10213 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx)) {
10214 hddLog(LOGE, FL("invalid argument pHddCtx"));
10215 return;
10216 }
10217
10218 if (NULL == lphbInd) {
10219 hddLog(LOGE, FL("invalid argument lphbInd"));
10220 return;
10221 }
10222
10223 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
10224 wiphy, sizeof(tSirLPHBInd),
10225 GFP_ATOMIC);
10226 if (!skb) {
10227 hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail"));
10228 return;
10229 }
10230
10231 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
10232 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail"));
10233 goto nla_put_failure;
10234 }
10235 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
10236 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail"));
10237 goto nla_put_failure;
10238 }
10239 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
10240 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail"));
10241 goto nla_put_failure;
10242 }
10243 cfg80211_testmode_event(skb, GFP_ATOMIC);
10244 return;
10245
10246nla_put_failure:
10247 hddLog(LOGE, FL("NLA Put fail"));
10248 kfree_skb(skb);
10249
10250 return;
10251}
10252#endif /* FEATURE_WLAN_LPHB */
10253
10254/**
10255 * __wlan_hdd_cfg80211_testmode() - test mode
10256 * @wiphy: Pointer to wiphy
10257 * @data: Data pointer
10258 * @len: Data length
10259 *
10260 * Return: 0 for success, non-zero for failure
10261 */
10262static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10263 void *data, int len)
10264{
10265 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
10266 int err;
10267 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10268
10269 err = wlan_hdd_validate_context(pHddCtx);
10270 if (err)
10271 return err;
10272
10273 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
10274 len, wlan_hdd_tm_policy);
10275 if (err) {
10276 hddLog(LOGE, FL("Testmode INV ATTR"));
10277 return err;
10278 }
10279
10280 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
10281 hddLog(LOGE, FL("Testmode INV CMD"));
10282 return -EINVAL;
10283 }
10284
10285 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
10286#ifdef FEATURE_WLAN_LPHB
10287 /* Low Power Heartbeat configuration request */
10288 case WLAN_HDD_TM_CMD_WLAN_HB:
10289 {
10290 int buf_len;
10291 void *buf;
10292 tSirLPHBReq *hb_params = NULL;
10293 tSirLPHBReq *hb_params_temp = NULL;
10294 CDF_STATUS smeStatus;
10295
10296 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
10297 hddLog(LOGE, FL("Testmode INV DATA"));
10298 return -EINVAL;
10299 }
10300
10301 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
10302 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
10303
10304 hb_params_temp = (tSirLPHBReq *) buf;
10305 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
10306 && (hb_params_temp->params.lphbTcpParamReq.
10307 timePeriodSec == 0))
10308 return -EINVAL;
10309
10310 hb_params =
10311 (tSirLPHBReq *) cdf_mem_malloc(sizeof(tSirLPHBReq));
10312 if (NULL == hb_params) {
10313 hddLog(LOGE, FL("Request Buffer Alloc Fail"));
10314 return -ENOMEM;
10315 }
10316
10317 cdf_mem_copy(hb_params, buf, buf_len);
10318 smeStatus =
10319 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
10320 hb_params,
10321 wlan_hdd_cfg80211_lphb_ind_handler);
10322 if (CDF_STATUS_SUCCESS != smeStatus) {
10323 hddLog(LOGE, "LPHB Config Fail, disable");
10324 cdf_mem_free(hb_params);
10325 }
10326 return 0;
10327 }
10328#endif /* FEATURE_WLAN_LPHB */
10329
10330#if defined(QCA_WIFI_FTM)
10331 case WLAN_HDD_TM_CMD_WLAN_FTM:
10332 {
10333 int buf_len;
10334 void *buf;
10335 CDF_STATUS status;
10336 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
10337 hddLog(LOGE,
10338 FL
10339 ("WLAN_HDD_TM_ATTR_DATA attribute is invalid"));
10340 return -EINVAL;
10341 }
10342
10343 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
10344 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
10345
10346 pr_info("****FTM Tx cmd len = %d*****\n", buf_len);
10347
10348 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
10349
10350 if (status != CDF_STATUS_SUCCESS)
10351 err = -EBUSY;
10352 break;
10353 }
10354#endif
10355
10356 default:
10357 hddLog(LOGE, FL("command %d not supported"),
10358 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
10359 return -EOPNOTSUPP;
10360 }
10361
10362 return err;
10363}
10364
10365/**
10366 * wlan_hdd_cfg80211_testmode() - test mode
10367 * @wiphy: Pointer to wiphy
10368 * @dev: Pointer to network device
10369 * @data: Data pointer
10370 * @len: Data length
10371 *
10372 * Return: 0 for success, non-zero for failure
10373 */
10374static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
10375#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
10376 struct wireless_dev *wdev,
10377#endif
10378 void *data, int len)
10379{
10380 int ret;
10381
10382 cds_ssr_protect(__func__);
10383 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
10384 cds_ssr_unprotect(__func__);
10385
10386 return ret;
10387}
10388
10389#if defined(QCA_WIFI_FTM)
10390/**
10391 * wlan_hdd_testmode_rx_event() - test mode rx event handler
10392 * @buf: Pointer to buffer
10393 * @buf_len: Buffer length
10394 *
10395 * Return: none
10396 */
10397void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
10398{
10399 struct sk_buff *skb;
10400 hdd_context_t *hdd_ctx;
10401
10402 if (!buf || !buf_len) {
10403 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
10404 "%s: buf or buf_len invalid, buf = %p buf_len = %zu",
10405 __func__, buf, buf_len);
10406 return;
10407 }
10408
10409 hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
10410 if (!hdd_ctx) {
10411 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
10412 "%s: hdd context invalid", __func__);
10413 return;
10414 }
10415
10416 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
10417 buf_len, GFP_KERNEL);
10418 if (!skb) {
10419 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
10420 "%s: failed to allocate testmode rx skb!", __func__);
10421 return;
10422 }
10423
10424 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
10425 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
10426 goto nla_put_failure;
10427
10428 pr_info("****FTM Rx cmd len = %zu*****\n", buf_len);
10429
10430 cfg80211_testmode_event(skb, GFP_KERNEL);
10431 return;
10432
10433nla_put_failure:
10434 kfree_skb(skb);
10435 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
10436 "%s: nla_put failed on testmode rx skb!", __func__);
10437}
10438#endif
10439#endif /* CONFIG_NL80211_TESTMODE */
10440
10441#ifdef QCA_HT_2040_COEX
10442/**
10443 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
10444 * @wiphy: Pointer to wiphy
10445 * @dev: Pointer to network device
10446 * @chandef: Pointer to channel definition parameter
10447 *
10448 * Return: 0 for success, non-zero for failure
10449 */
10450static int
10451__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
10452 struct net_device *dev,
10453 struct cfg80211_chan_def *chandef)
10454{
10455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10456 hdd_context_t *pHddCtx;
10457 CDF_STATUS status;
10458 tSmeConfigParams sme_config;
10459 bool cbModeChange;
10460
10461 if (CDF_FTM_MODE == hdd_get_conparam()) {
10462 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10463 return -EINVAL;
10464 }
10465
10466 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10467 status = wlan_hdd_validate_context(pHddCtx);
10468
10469 if (0 != status) {
10470 hddLog(LOGE, FL("HDD context is not valid"));
10471 return status;
10472 }
10473
10474 cdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
10475 sme_get_config_param(pHddCtx->hHal, &sme_config);
10476 switch (chandef->width) {
10477 case NL80211_CHAN_WIDTH_20:
10478 if (sme_config.csrConfig.channelBondingMode24GHz !=
10479 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
10480 sme_config.csrConfig.channelBondingMode24GHz =
10481 eCSR_INI_SINGLE_CHANNEL_CENTERED;
10482 sme_update_config(pHddCtx->hHal, &sme_config);
10483 cbModeChange = true;
10484 }
10485 break;
10486
10487 case NL80211_CHAN_WIDTH_40:
10488 if (sme_config.csrConfig.channelBondingMode24GHz ==
10489 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
10490 if (NL80211_CHAN_HT40MINUS ==
10491 cfg80211_get_chandef_type(chandef))
10492 sme_config.csrConfig.channelBondingMode24GHz =
10493 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
10494 else
10495 sme_config.csrConfig.channelBondingMode24GHz =
10496 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
10497 sme_update_config(pHddCtx->hHal, &sme_config);
10498 cbModeChange = true;
10499 }
10500 break;
10501
10502 default:
10503 hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !"));
10504 return -EINVAL;
10505 }
10506
10507 if (!cbModeChange)
10508 return 0;
10509
10510 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
10511 return 0;
10512
10513 hddLog(LOG1, FL("Channel bonding changed to %d"),
10514 sme_config.csrConfig.channelBondingMode24GHz);
10515
10516 /* Change SAP ht2040 mode */
10517 status = hdd_set_sap_ht2040_mode(pAdapter,
10518 cfg80211_get_chandef_type(chandef));
10519 if (status != CDF_STATUS_SUCCESS) {
10520 hddLog(LOGE, FL("Error!!! Cannot set SAP HT20/40 mode!"));
10521 return -EINVAL;
10522 }
10523
10524 return 0;
10525}
10526
10527/**
10528 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
10529 * @wiphy: Pointer to wiphy
10530 * @dev: Pointer to network device
10531 * @chandef: Pointer to channel definition parameter
10532 *
10533 * Return: 0 for success, non-zero for failure
10534 */
10535static int
10536wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
10537 struct net_device *dev,
10538 struct cfg80211_chan_def *chandef)
10539{
10540 int ret;
10541
10542 cds_ssr_protect(__func__);
10543 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
10544 cds_ssr_unprotect(__func__);
10545
10546 return ret;
10547}
10548#endif
10549
10550/**
10551 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
10552 * translation from NL to policy manager type
10553 * @type: Generic connection mode type defined in NL
10554 *
10555 *
10556 * This function provides the type translation
10557 *
10558 * Return: cds_con_mode enum
10559 */
10560enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
10561 enum nl80211_iftype type)
10562{
10563 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
10564 switch (type) {
10565 case NL80211_IFTYPE_STATION:
10566 mode = CDS_STA_MODE;
10567 break;
10568 case NL80211_IFTYPE_P2P_CLIENT:
10569 mode = CDS_P2P_CLIENT_MODE;
10570 break;
10571 case NL80211_IFTYPE_P2P_GO:
10572 mode = CDS_P2P_GO_MODE;
10573 break;
10574 case NL80211_IFTYPE_AP:
10575 mode = CDS_SAP_MODE;
10576 break;
10577 case NL80211_IFTYPE_ADHOC:
10578 mode = CDS_IBSS_MODE;
10579 break;
10580 default:
10581 hddLog(LOGE, FL("Unsupported interface type (%d)"),
10582 type);
10583 }
10584 return mode;
10585}
10586
10587/**
10588 * struct cfg80211_ops - cfg80211_ops
10589 *
10590 * @add_virtual_intf: Add virtual interface
10591 * @del_virtual_intf: Delete virtual interface
10592 * @change_virtual_intf: Change virtual interface
10593 * @change_station: Change station
10594 * @add_beacon: Add beacon in sap mode
10595 * @del_beacon: Delete beacon in sap mode
10596 * @set_beacon: Set beacon in sap mode
10597 * @start_ap: Start ap
10598 * @change_beacon: Change beacon
10599 * @stop_ap: Stop ap
10600 * @change_bss: Change bss
10601 * @add_key: Add key
10602 * @get_key: Get key
10603 * @del_key: Delete key
10604 * @set_default_key: Set default key
10605 * @set_channel: Set channel
10606 * @scan: Scan
10607 * @connect: Connect
10608 * @disconnect: Disconnect
10609 * @join_ibss = Join ibss
10610 * @leave_ibss = Leave ibss
10611 * @set_wiphy_params = Set wiphy params
10612 * @set_tx_power = Set tx power
10613 * @get_tx_power = get tx power
10614 * @remain_on_channel = Remain on channel
10615 * @cancel_remain_on_channel = Cancel remain on channel
10616 * @mgmt_tx = Tx management frame
10617 * @mgmt_tx_cancel_wait = Cancel management tx wait
10618 * @set_default_mgmt_key = Set default management key
10619 * @set_txq_params = Set tx queue parameters
10620 * @get_station = Get station
10621 * @set_power_mgmt = Set power management
10622 * @del_station = Delete station
10623 * @add_station = Add station
10624 * @set_pmksa = Set pmksa
10625 * @del_pmksa = Delete pmksa
10626 * @flush_pmksa = Flush pmksa
10627 * @update_ft_ies = Update FT IEs
10628 * @tdls_mgmt = Tdls management
10629 * @tdls_oper = Tdls operation
10630 * @set_rekey_data = Set rekey data
10631 * @sched_scan_start = Scheduled scan start
10632 * @sched_scan_stop = Scheduled scan stop
10633 * @resume = Resume wlan
10634 * @suspend = Suspend wlan
10635 * @set_mac_acl = Set mac acl
10636 * @testmode_cmd = Test mode command
10637 * @set_ap_chanwidth = Set AP channel bandwidth
10638 * @dump_survey = Dump survey
10639 * @key_mgmt_set_pmk = Set pmk key management
10640 */
10641static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
10642 .add_virtual_intf = wlan_hdd_add_virtual_intf,
10643 .del_virtual_intf = wlan_hdd_del_virtual_intf,
10644 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
10645 .change_station = wlan_hdd_change_station,
10646#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
10647 .add_beacon = wlan_hdd_cfg80211_add_beacon,
10648 .del_beacon = wlan_hdd_cfg80211_del_beacon,
10649 .set_beacon = wlan_hdd_cfg80211_set_beacon,
10650#else
10651 .start_ap = wlan_hdd_cfg80211_start_ap,
10652 .change_beacon = wlan_hdd_cfg80211_change_beacon,
10653 .stop_ap = wlan_hdd_cfg80211_stop_ap,
10654#endif
10655 .change_bss = wlan_hdd_cfg80211_change_bss,
10656 .add_key = wlan_hdd_cfg80211_add_key,
10657 .get_key = wlan_hdd_cfg80211_get_key,
10658 .del_key = wlan_hdd_cfg80211_del_key,
10659 .set_default_key = wlan_hdd_cfg80211_set_default_key,
10660 .scan = wlan_hdd_cfg80211_scan,
10661 .connect = wlan_hdd_cfg80211_connect,
10662 .disconnect = wlan_hdd_cfg80211_disconnect,
10663 .join_ibss = wlan_hdd_cfg80211_join_ibss,
10664 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
10665 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
10666 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
10667 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
10668 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
10669 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
10670 .mgmt_tx = wlan_hdd_mgmt_tx,
10671 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
10672 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
10673 .set_txq_params = wlan_hdd_set_txq_params,
10674 .get_station = wlan_hdd_cfg80211_get_station,
10675 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
10676 .del_station = wlan_hdd_cfg80211_del_station,
10677 .add_station = wlan_hdd_cfg80211_add_station,
10678#ifdef FEATURE_WLAN_LFR
10679 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
10680 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
10681 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
10682#endif
10683#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
10684 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
10685#endif
10686#ifdef FEATURE_WLAN_TDLS
10687 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
10688 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
10689#endif
10690#ifdef WLAN_FEATURE_GTK_OFFLOAD
10691 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
10692#endif /* WLAN_FEATURE_GTK_OFFLOAD */
10693#ifdef FEATURE_WLAN_SCAN_PNO
10694 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
10695 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
10696#endif /*FEATURE_WLAN_SCAN_PNO */
10697 .resume = wlan_hdd_cfg80211_resume_wlan,
10698 .suspend = wlan_hdd_cfg80211_suspend_wlan,
10699 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
10700#ifdef WLAN_NL80211_TESTMODE
10701 .testmode_cmd = wlan_hdd_cfg80211_testmode,
10702#endif
10703#ifdef QCA_HT_2040_COEX
10704 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
10705#endif
10706 .dump_survey = wlan_hdd_cfg80211_dump_survey,
10707};