blob: 74a13be47c3a24d28d122e7c9518c17c2e9db4d5 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
69#include "wlan_hdd_misc.h"
70#include "wlan_hdd_nan.h"
71#include <wlan_hdd_ipa.h>
72#include "wlan_logging_sock_svc.h"
73
74#ifdef FEATURE_WLAN_EXTSCAN
75#include "wlan_hdd_ext_scan.h"
76#endif
77
78#ifdef WLAN_FEATURE_LINK_LAYER_STATS
79#include "wlan_hdd_stats.h"
80#endif
81#include "cds_concurrency.h"
82#include "qwlan_version.h"
83#include "wlan_hdd_memdump.h"
84
85#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070086#include "wlan_hdd_tsf.h"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070087#include "ol_txrx.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088
Ravi Joshideb5a8d2015-11-09 19:11:43 -080089#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053090#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070091#include "wlan_hdd_lpass.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#define g_mode_rates_size (12)
94#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
96 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
97
98/*
99 * Android CTS verifier needs atleast this much wait time (in msec)
100 */
101#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
102
103/*
104 * Refer @tCfgProtection structure for definition of the bit map.
105 * below value is obtained by setting the following bit-fields.
106 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
107 */
108#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
109
110#define HDD2GHZCHAN(freq, chan, flag) { \
111 .band = IEEE80211_BAND_2GHZ, \
112 .center_freq = (freq), \
113 .hw_value = (chan), \
114 .flags = (flag), \
115 .max_antenna_gain = 0, \
116 .max_power = 30, \
117}
118
119#define HDD5GHZCHAN(freq, chan, flag) { \
120 .band = IEEE80211_BAND_5GHZ, \
121 .center_freq = (freq), \
122 .hw_value = (chan), \
123 .flags = (flag), \
124 .max_antenna_gain = 0, \
125 .max_power = 30, \
126}
127
128#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
129 { \
130 .bitrate = rate, \
131 .hw_value = rate_id, \
132 .flags = flag, \
133 }
134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
136#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800137
138#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139
Peng Xu4d67c8f2015-10-16 16:02:26 -0700140#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530141#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143static const u32 hdd_cipher_suites[] = {
144 WLAN_CIPHER_SUITE_WEP40,
145 WLAN_CIPHER_SUITE_WEP104,
146 WLAN_CIPHER_SUITE_TKIP,
147#ifdef FEATURE_WLAN_ESE
148#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
149#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
150 WLAN_CIPHER_SUITE_BTK,
151 WLAN_CIPHER_SUITE_KRK,
152 WLAN_CIPHER_SUITE_CCMP,
153#else
154 WLAN_CIPHER_SUITE_CCMP,
155#endif
156#ifdef FEATURE_WLAN_WAPI
157 WLAN_CIPHER_SUITE_SMS4,
158#endif
159#ifdef WLAN_FEATURE_11W
160 WLAN_CIPHER_SUITE_AES_CMAC,
161#endif
162};
163
Abhishek Singhf512bf32016-05-04 16:47:46 +0530164static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165 HDD2GHZCHAN(2412, 1, 0),
166 HDD2GHZCHAN(2417, 2, 0),
167 HDD2GHZCHAN(2422, 3, 0),
168 HDD2GHZCHAN(2427, 4, 0),
169 HDD2GHZCHAN(2432, 5, 0),
170 HDD2GHZCHAN(2437, 6, 0),
171 HDD2GHZCHAN(2442, 7, 0),
172 HDD2GHZCHAN(2447, 8, 0),
173 HDD2GHZCHAN(2452, 9, 0),
174 HDD2GHZCHAN(2457, 10, 0),
175 HDD2GHZCHAN(2462, 11, 0),
176 HDD2GHZCHAN(2467, 12, 0),
177 HDD2GHZCHAN(2472, 13, 0),
178 HDD2GHZCHAN(2484, 14, 0),
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD5GHZCHAN(5180, 36, 0),
183 HDD5GHZCHAN(5200, 40, 0),
184 HDD5GHZCHAN(5220, 44, 0),
185 HDD5GHZCHAN(5240, 48, 0),
186 HDD5GHZCHAN(5260, 52, 0),
187 HDD5GHZCHAN(5280, 56, 0),
188 HDD5GHZCHAN(5300, 60, 0),
189 HDD5GHZCHAN(5320, 64, 0),
190 HDD5GHZCHAN(5500, 100, 0),
191 HDD5GHZCHAN(5520, 104, 0),
192 HDD5GHZCHAN(5540, 108, 0),
193 HDD5GHZCHAN(5560, 112, 0),
194 HDD5GHZCHAN(5580, 116, 0),
195 HDD5GHZCHAN(5600, 120, 0),
196 HDD5GHZCHAN(5620, 124, 0),
197 HDD5GHZCHAN(5640, 128, 0),
198 HDD5GHZCHAN(5660, 132, 0),
199 HDD5GHZCHAN(5680, 136, 0),
200 HDD5GHZCHAN(5700, 140, 0),
201 HDD5GHZCHAN(5720, 144, 0),
202 HDD5GHZCHAN(5745, 149, 0),
203 HDD5GHZCHAN(5765, 153, 0),
204 HDD5GHZCHAN(5785, 157, 0),
205 HDD5GHZCHAN(5805, 161, 0),
206 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 HDD5GHZCHAN(5852, 170, 0),
208 HDD5GHZCHAN(5855, 171, 0),
209 HDD5GHZCHAN(5860, 172, 0),
210 HDD5GHZCHAN(5865, 173, 0),
211 HDD5GHZCHAN(5870, 174, 0),
212 HDD5GHZCHAN(5875, 175, 0),
213 HDD5GHZCHAN(5880, 176, 0),
214 HDD5GHZCHAN(5885, 177, 0),
215 HDD5GHZCHAN(5890, 178, 0),
216 HDD5GHZCHAN(5895, 179, 0),
217 HDD5GHZCHAN(5900, 180, 0),
218 HDD5GHZCHAN(5905, 181, 0),
219 HDD5GHZCHAN(5910, 182, 0),
220 HDD5GHZCHAN(5915, 183, 0),
221 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222};
223
224static struct ieee80211_rate g_mode_rates[] = {
225 HDD_G_MODE_RATETAB(10, 0x1, 0),
226 HDD_G_MODE_RATETAB(20, 0x2, 0),
227 HDD_G_MODE_RATETAB(55, 0x4, 0),
228 HDD_G_MODE_RATETAB(110, 0x8, 0),
229 HDD_G_MODE_RATETAB(60, 0x10, 0),
230 HDD_G_MODE_RATETAB(90, 0x20, 0),
231 HDD_G_MODE_RATETAB(120, 0x40, 0),
232 HDD_G_MODE_RATETAB(180, 0x80, 0),
233 HDD_G_MODE_RATETAB(240, 0x100, 0),
234 HDD_G_MODE_RATETAB(360, 0x200, 0),
235 HDD_G_MODE_RATETAB(480, 0x400, 0),
236 HDD_G_MODE_RATETAB(540, 0x800, 0),
237};
238
239static struct ieee80211_rate a_mode_rates[] = {
240 HDD_G_MODE_RATETAB(60, 0x10, 0),
241 HDD_G_MODE_RATETAB(90, 0x20, 0),
242 HDD_G_MODE_RATETAB(120, 0x40, 0),
243 HDD_G_MODE_RATETAB(180, 0x80, 0),
244 HDD_G_MODE_RATETAB(240, 0x100, 0),
245 HDD_G_MODE_RATETAB(360, 0x200, 0),
246 HDD_G_MODE_RATETAB(480, 0x400, 0),
247 HDD_G_MODE_RATETAB(540, 0x800, 0),
248};
249
250static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530251 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
253 .band = IEEE80211_BAND_2GHZ,
254 .bitrates = g_mode_rates,
255 .n_bitrates = g_mode_rates_size,
256 .ht_cap.ht_supported = 1,
257 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
258 | IEEE80211_HT_CAP_GRN_FLD
259 | IEEE80211_HT_CAP_DSSSCCK40
260 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
261 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
262 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
263 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
264 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
265 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
266 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
267};
268
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530270 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
272 .band = IEEE80211_BAND_5GHZ,
273 .bitrates = a_mode_rates,
274 .n_bitrates = a_mode_rates_size,
275 .ht_cap.ht_supported = 1,
276 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
277 | IEEE80211_HT_CAP_GRN_FLD
278 | IEEE80211_HT_CAP_DSSSCCK40
279 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
280 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
281 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
282 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
283 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
284 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
285 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
286 .vht_cap.vht_supported = 1,
287};
288
289/* This structure contain information what kind of frame are expected in
290 TX/RX direction for each kind of interface */
291static const struct ieee80211_txrx_stypes
292 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
293 [NL80211_IFTYPE_STATION] = {
294 .tx = 0xffff,
295 .rx = BIT(SIR_MAC_MGMT_ACTION) |
296 BIT(SIR_MAC_MGMT_PROBE_REQ),
297 },
298 [NL80211_IFTYPE_AP] = {
299 .tx = 0xffff,
300 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
301 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
302 BIT(SIR_MAC_MGMT_PROBE_REQ) |
303 BIT(SIR_MAC_MGMT_DISASSOC) |
304 BIT(SIR_MAC_MGMT_AUTH) |
305 BIT(SIR_MAC_MGMT_DEAUTH) |
306 BIT(SIR_MAC_MGMT_ACTION),
307 },
308 [NL80211_IFTYPE_ADHOC] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
311 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
312 BIT(SIR_MAC_MGMT_PROBE_REQ) |
313 BIT(SIR_MAC_MGMT_DISASSOC) |
314 BIT(SIR_MAC_MGMT_AUTH) |
315 BIT(SIR_MAC_MGMT_DEAUTH) |
316 BIT(SIR_MAC_MGMT_ACTION),
317 },
318 [NL80211_IFTYPE_P2P_CLIENT] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ACTION) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ),
322 },
323 [NL80211_IFTYPE_P2P_GO] = {
324 /* This is also same as for SoftAP */
325 .tx = 0xffff,
326 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_PROBE_REQ) |
329 BIT(SIR_MAC_MGMT_DISASSOC) |
330 BIT(SIR_MAC_MGMT_AUTH) |
331 BIT(SIR_MAC_MGMT_DEAUTH) |
332 BIT(SIR_MAC_MGMT_ACTION),
333 },
334};
335
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800336/* Interface limits and combinations registered by the driver */
337
338/* STA ( + STA ) combination */
339static const struct ieee80211_iface_limit
340 wlan_hdd_sta_iface_limit[] = {
341 {
342 .max = 3, /* p2p0 is a STA as well */
343 .types = BIT(NL80211_IFTYPE_STATION),
344 },
345};
346
Krunal Soni7bc4f912015-11-15 23:41:56 -0800347#ifndef QCA_WIFI_3_0_EMU
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800348/* ADHOC (IBSS) limit */
349static const struct ieee80211_iface_limit
350 wlan_hdd_adhoc_iface_limit[] = {
351 {
352 .max = 1,
353 .types = BIT(NL80211_IFTYPE_STATION),
354 },
355 {
356 .max = 1,
357 .types = BIT(NL80211_IFTYPE_ADHOC),
358 },
359};
Krunal Soni7bc4f912015-11-15 23:41:56 -0800360#else
361/* ADHOC (IBSS) limit */
362static const struct ieee80211_iface_limit
363 wlan_hdd_adhoc_iface_limit[] = {
364 {
365 .max = 1,
366 .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
367 },
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_ADHOC),
371 },
372};
373#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374
375/* AP ( + AP ) combination */
376static const struct ieee80211_iface_limit
377 wlan_hdd_ap_iface_limit[] = {
378 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530379 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 .types = BIT(NL80211_IFTYPE_AP),
381 },
382};
383
384/* P2P limit */
385static const struct ieee80211_iface_limit
386 wlan_hdd_p2p_iface_limit[] = {
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO),
394 },
395};
396
397static const struct ieee80211_iface_limit
398 wlan_hdd_sta_ap_iface_limit[] = {
399 {
400 /* We need 1 extra STA interface for OBSS scan when SAP starts
401 * with HT40 in STA+SAP concurrency mode
402 */
403 .max = (1 + SAP_MAX_OBSS_STA_CNT),
404 .types = BIT(NL80211_IFTYPE_STATION),
405 },
406 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530407 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 .types = BIT(NL80211_IFTYPE_AP),
409 },
410};
411
412/* STA + P2P combination */
413static const struct ieee80211_iface_limit
414 wlan_hdd_sta_p2p_iface_limit[] = {
415 {
416 /* One reserved for dedicated P2PDEV usage */
417 .max = 2,
418 .types = BIT(NL80211_IFTYPE_STATION)
419 },
420 {
421 /* Support for two identical (GO + GO or CLI + CLI)
422 * or dissimilar (GO + CLI) P2P interfaces
423 */
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
426 },
427};
428
429/* STA + AP + P2PGO combination */
430static const struct ieee80211_iface_limit
431wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
432 /* Support for AP+P2PGO interfaces */
433 {
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_STATION)
436 },
437 {
438 .max = 1,
439 .types = BIT(NL80211_IFTYPE_P2P_GO)
440 },
441 {
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_AP)
444 }
445};
446
447/* SAP + P2P combination */
448static const struct ieee80211_iface_limit
449wlan_hdd_sap_p2p_iface_limit[] = {
450 {
451 /* 1 dedicated for p2p0 which is a STA type */
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_STATION)
454 },
455 {
456 /* The p2p interface in SAP+P2P can be GO/CLI.
457 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
458 */
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
461 },
462 {
463 /* SAP+GO to support only one SAP interface */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_AP)
466 }
467};
468
469/* P2P + P2P combination */
470static const struct ieee80211_iface_limit
471wlan_hdd_p2p_p2p_iface_limit[] = {
472 {
473 /* 1 dedicated for p2p0 which is a STA type */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_STATION)
476 },
477 {
478 /* The p2p interface in P2P+P2P can be GO/CLI.
479 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
480 */
481 .max = 2,
482 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
483 },
484};
485
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700486static const struct ieee80211_iface_limit
487 wlan_hdd_mon_iface_limit[] = {
488 {
489 .max = 3, /* Monitor interface */
490 .types = BIT(NL80211_IFTYPE_MONITOR),
491 },
492};
493
494static struct ieee80211_iface_combination
495 wlan_hdd_mon_iface[] = {
496 {
497 .limits = wlan_hdd_mon_iface_limit,
498 .max_interfaces = 3,
499 .num_different_channels = 2,
500 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
501 },
502};
503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504static struct ieee80211_iface_combination
505 wlan_hdd_iface_combination[] = {
506 /* STA */
507 {
508 .limits = wlan_hdd_sta_iface_limit,
509 .num_different_channels = 2,
510 .max_interfaces = 3,
511 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
512 },
513 /* ADHOC */
514 {
515 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700516 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 .max_interfaces = 2,
518 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
519 },
520 /* AP */
521 {
522 .limits = wlan_hdd_ap_iface_limit,
523 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
526 },
527 /* P2P */
528 {
529 .limits = wlan_hdd_p2p_iface_limit,
530 .num_different_channels = 2,
531 .max_interfaces = 2,
532 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
533 },
534 /* STA + AP */
535 {
536 .limits = wlan_hdd_sta_ap_iface_limit,
537 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530538 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
540 .beacon_int_infra_match = true,
541 },
542 /* STA + P2P */
543 {
544 .limits = wlan_hdd_sta_p2p_iface_limit,
545 .num_different_channels = 2,
546 /* one interface reserved for P2PDEV dedicated usage */
547 .max_interfaces = 4,
548 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
549 .beacon_int_infra_match = true,
550 },
551 /* STA + P2P GO + SAP */
552 {
553 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
554 /* we can allow 3 channels for three different persona
555 * but due to firmware limitation, allow max 2 concrnt channels.
556 */
557 .num_different_channels = 2,
558 /* one interface reserved for P2PDEV dedicated usage */
559 .max_interfaces = 4,
560 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
561 .beacon_int_infra_match = true,
562 },
563 /* SAP + P2P */
564 {
565 .limits = wlan_hdd_sap_p2p_iface_limit,
566 .num_different_channels = 2,
567 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
568 .max_interfaces = 3,
569 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
570 .beacon_int_infra_match = true,
571 },
572 /* P2P + P2P */
573 {
574 .limits = wlan_hdd_p2p_p2p_iface_limit,
575 .num_different_channels = 2,
576 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
577 .max_interfaces = 3,
578 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
579 .beacon_int_infra_match = true,
580 },
581};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530584struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
605static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
606 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
607 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
608 .len = WLAN_HDD_TM_DATA_MAX_LEN},
609};
610#endif /* WLAN_NL80211_TESTMODE */
611
612#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
613static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
614 .flags = WIPHY_WOWLAN_MAGIC_PKT,
615 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
616 .pattern_min_len = 1,
617 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
618};
619#endif
620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800621/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530622 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
623 * @flags: Pointer to the flags to Add channel switch flag.
624 *
625 * This Function adds Channel Switch support flag, if channel switch is
626 * supported by kernel.
627 * Return: void.
628 */
629#ifdef CHANNEL_SWITCH_SUPPORTED
630static inline void hdd_add_channel_switch_support(uint32_t *flags)
631{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800632 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530633 return;
634}
635#else
636static inline void hdd_add_channel_switch_support(uint32_t *flags)
637{
638 return;
639}
640#endif
641
Manikandan Mohan22b83722015-12-15 15:03:23 -0800642#ifdef FEATURE_WLAN_TDLS
643
644/* TDLS capabilities params */
645#define PARAM_MAX_TDLS_SESSION \
646 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
647#define PARAM_TDLS_FEATURE_SUPPORT \
648 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
649
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530650/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
652 * @wiphy: WIPHY structure pointer
653 * @wdev: Wireless device structure pointer
654 * @data: Pointer to the data received
655 * @data_len: Length of the data received
656 *
657 * This function provides TDLS capabilities
658 *
659 * Return: 0 on success and errno on failure
660 */
661static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
662 struct wireless_dev *wdev,
663 const void *data,
664 int data_len)
665{
666 int status;
667 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
668 struct sk_buff *skb;
669 uint32_t set = 0;
670
Jeff Johnson1f61b612016-02-12 16:28:33 -0800671 ENTER_DEV(wdev->netdev);
672
Anurag Chouhan6d760662016-02-20 16:05:43 +0530673 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800674 hdd_err("Command not allowed in FTM mode");
675 return -EPERM;
676 }
677
678 status = wlan_hdd_validate_context(hdd_ctx);
679 if (status)
680 return status;
681
682 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
683 NLMSG_HDRLEN);
684 if (!skb) {
685 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
686 goto fail;
687 }
688
689 if (false == hdd_ctx->config->fEnableTDLSSupport) {
690 hddLog(LOGE,
691 FL("TDLS feature not Enabled or Not supported in FW"));
692 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
693 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
694 hddLog(LOGE, FL("nla put fail"));
695 goto fail;
696 }
697 } else {
698 set = set | WIFI_TDLS_SUPPORT;
699 set = set | (hdd_ctx->config->fTDLSExternalControl ?
700 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
701 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
702 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
703 hddLog(LOG1, FL("TDLS Feature supported value %x"), set);
704 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
705 hdd_ctx->max_num_tdls_sta) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
707 set)) {
708 hddLog(LOGE, FL("nla put fail"));
709 goto fail;
710 }
711 }
712 return cfg80211_vendor_cmd_reply(skb);
713fail:
714 if (skb)
715 kfree_skb(skb);
716 return -EINVAL;
717}
718
719/**
720 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
721 * @wiphy: WIPHY structure pointer
722 * @wdev: Wireless device structure pointer
723 * @data: Pointer to the data received
724 * @data_len: Length of the data received
725 *
726 * This function provides TDLS capabilities
727 *
728 * Return: 0 on success and errno on failure
729 */
730static int
731wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
732 struct wireless_dev *wdev,
733 const void *data,
734 int data_len)
735{
736 int ret;
737
738 cds_ssr_protect(__func__);
739 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
740 data, data_len);
741 cds_ssr_unprotect(__func__);
742
743 return ret;
744}
745#endif
746
747#ifdef QCA_HT_2040_COEX
748static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
749#endif
750
751#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
752/*
753 * FUNCTION: wlan_hdd_send_avoid_freq_event
754 * This is called when wlan driver needs to send vendor specific
755 * avoid frequency range event to userspace
756 */
757int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
758 tHddAvoidFreqList *pAvoidFreqList)
759{
760 struct sk_buff *vendor_event;
761
762 ENTER();
763
764 if (!pHddCtx) {
765 hddLog(LOGE, FL("HDD context is null"));
766 return -EINVAL;
767 }
768
769 if (!pAvoidFreqList) {
770 hddLog(LOGE, FL("pAvoidFreqList is null"));
771 return -EINVAL;
772 }
773
774 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
775 NULL,
776 sizeof(tHddAvoidFreqList),
777 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
778 GFP_KERNEL);
779 if (!vendor_event) {
780 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
781 return -EINVAL;
782 }
783
784 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
785 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
786
787 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
788
789 EXIT();
790 return 0;
791}
792#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
793
794/* vendor specific events */
795static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
796#ifdef FEATURE_WLAN_CH_AVOID
797 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
798 .vendor_id =
799 QCA_NL80211_VENDOR_ID,
800 .subcmd =
801 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
802 },
803#endif /* FEATURE_WLAN_CH_AVOID */
804
805#ifdef WLAN_FEATURE_NAN
806 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
807 .vendor_id =
808 QCA_NL80211_VENDOR_ID,
809 .subcmd =
810 QCA_NL80211_VENDOR_SUBCMD_NAN
811 },
812#endif
813
814#ifdef WLAN_FEATURE_STATS_EXT
815 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
820 },
821#endif /* WLAN_FEATURE_STATS_EXT */
822#ifdef FEATURE_WLAN_EXTSCAN
823 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
824 .vendor_id =
825 QCA_NL80211_VENDOR_ID,
826 .subcmd =
827 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
828 },
829 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
830 .vendor_id =
831 QCA_NL80211_VENDOR_ID,
832 .subcmd =
833 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
834 },
835 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
836 .
837 vendor_id
838 =
839 QCA_NL80211_VENDOR_ID,
840 .subcmd =
841 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
842 },
843 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
844 .
845 vendor_id
846 =
847 QCA_NL80211_VENDOR_ID,
848 .
849 subcmd =
850 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
851 },
852 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
853 .
854 vendor_id
855 =
856 QCA_NL80211_VENDOR_ID,
857 .
858 subcmd
859 =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .subcmd =
868 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
869 },
870 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
871 .vendor_id =
872 QCA_NL80211_VENDOR_ID,
873 .subcmd =
874 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
875 },
876 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
877 .
878 vendor_id
879 =
880 QCA_NL80211_VENDOR_ID,
881 .subcmd =
882 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
883 },
884 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
885 .
886 vendor_id
887 =
888 QCA_NL80211_VENDOR_ID,
889 .subcmd =
890 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
891 },
892 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
893 .
894 vendor_id
895 =
896 QCA_NL80211_VENDOR_ID,
897 .
898 subcmd
899 =
900 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
901 },
902 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
903 .
904 vendor_id
905 =
906 QCA_NL80211_VENDOR_ID,
907 .
908 subcmd =
909 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
910 },
911 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
912 .
913 vendor_id
914 =
915 QCA_NL80211_VENDOR_ID,
916 .
917 subcmd
918 =
919 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
922 .
923 vendor_id
924 =
925 QCA_NL80211_VENDOR_ID,
926 .
927 subcmd
928 =
929 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
930 },
931 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
932 .vendor_id = QCA_NL80211_VENDOR_ID,
933 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
938 },
939#endif /* FEATURE_WLAN_EXTSCAN */
940
941#ifdef WLAN_FEATURE_LINK_LAYER_STATS
942 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
943 .vendor_id =
944 QCA_NL80211_VENDOR_ID,
945 .subcmd =
946 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
947 },
948 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
949 .vendor_id =
950 QCA_NL80211_VENDOR_ID,
951 .subcmd =
952 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
953 },
954 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
955 .vendor_id =
956 QCA_NL80211_VENDOR_ID,
957 .subcmd =
958 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
959 },
960 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
961 .vendor_id =
962 QCA_NL80211_VENDOR_ID,
963 .subcmd =
964 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
965 },
966 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
967 .vendor_id =
968 QCA_NL80211_VENDOR_ID,
969 .subcmd =
970 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
971 },
972 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
973 .vendor_id =
974 QCA_NL80211_VENDOR_ID,
975 .subcmd =
976 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
977 },
978#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
979 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
980 .vendor_id =
981 QCA_NL80211_VENDOR_ID,
982 .subcmd =
983 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
984 },
985 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
986 .vendor_id = QCA_NL80211_VENDOR_ID,
987 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
988 },
989#ifdef WLAN_FEATURE_ROAM_OFFLOAD
990 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
995 },
996#endif
997 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
998 .vendor_id =
999 QCA_NL80211_VENDOR_ID,
1000 .subcmd =
1001 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1002 },
1003 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1004 .vendor_id =
1005 QCA_NL80211_VENDOR_ID,
1006 .subcmd =
1007 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1008 },
1009 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1010 .vendor_id =
1011 QCA_NL80211_VENDOR_ID,
1012 .subcmd =
1013 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1014 },
1015 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1016 .vendor_id =
1017 QCA_NL80211_VENDOR_ID,
1018 .subcmd =
1019 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1020 },
1021 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1022 .vendor_id =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1026 },
1027#ifdef FEATURE_WLAN_EXTSCAN
1028 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1029 .vendor_id = QCA_NL80211_VENDOR_ID,
1030 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1031 },
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1047 },
1048#endif /* FEATURE_WLAN_EXTSCAN */
1049 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1050 .vendor_id = QCA_NL80211_VENDOR_ID,
1051 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1052 },
1053#ifdef WLAN_FEATURE_MEMDUMP
1054 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1057 },
1058#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001059#ifdef WLAN_FEATURE_TSF
1060 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1063 },
1064#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001065 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1066 .vendor_id = QCA_NL80211_VENDOR_ID,
1067 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1068 },
1069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1072 },
1073 /* OCB events */
1074 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1075 .vendor_id = QCA_NL80211_VENDOR_ID,
1076 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1077 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001078#ifdef FEATURE_LFR_SUBNET_DETECTION
1079 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1080 .vendor_id = QCA_NL80211_VENDOR_ID,
1081 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1082 },
1083#endif /*FEATURE_LFR_SUBNET_DETECTION */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001084};
1085
1086/**
1087 * __is_driver_dfs_capable() - get driver DFS capability
1088 * @wiphy: pointer to wireless wiphy structure.
1089 * @wdev: pointer to wireless_dev structure.
1090 * @data: Pointer to the data to be passed via vendor interface
1091 * @data_len:Length of the data to be passed
1092 *
1093 * This function is called by userspace to indicate whether or not
1094 * the driver supports DFS offload.
1095 *
1096 * Return: 0 on success, negative errno on failure
1097 */
1098static int __is_driver_dfs_capable(struct wiphy *wiphy,
1099 struct wireless_dev *wdev,
1100 const void *data,
1101 int data_len)
1102{
1103 u32 dfs_capability = 0;
1104 struct sk_buff *temp_skbuff;
1105 int ret_val;
1106 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1107
Jeff Johnson1f61b612016-02-12 16:28:33 -08001108 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109
1110 ret_val = wlan_hdd_validate_context(hdd_ctx);
1111 if (ret_val)
1112 return ret_val;
1113
Anurag Chouhan6d760662016-02-20 16:05:43 +05301114 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115 hdd_err("Command not allowed in FTM mode");
1116 return -EPERM;
1117 }
1118
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001119 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001120
1121 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1122 NLMSG_HDRLEN);
1123
1124 if (temp_skbuff != NULL) {
1125 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1126 dfs_capability);
1127 if (ret_val) {
1128 hddLog(LOGE, FL("QCA_WLAN_VENDOR_ATTR_DFS put fail"));
1129 kfree_skb(temp_skbuff);
1130
1131 return ret_val;
1132 }
1133
1134 return cfg80211_vendor_cmd_reply(temp_skbuff);
1135 }
1136
1137 hddLog(LOGE, FL("dfs capability: buffer alloc fail"));
1138 return -ENOMEM;
1139}
1140
1141/**
1142 * is_driver_dfs_capable() - get driver DFS capability
1143 * @wiphy: pointer to wireless wiphy structure.
1144 * @wdev: pointer to wireless_dev structure.
1145 * @data: Pointer to the data to be passed via vendor interface
1146 * @data_len:Length of the data to be passed
1147 *
1148 * This function is called by userspace to indicate whether or not
1149 * the driver supports DFS offload. This is an SSR-protected
1150 * wrapper function.
1151 *
1152 * Return: 0 on success, negative errno on failure
1153 */
1154static int is_driver_dfs_capable(struct wiphy *wiphy,
1155 struct wireless_dev *wdev,
1156 const void *data,
1157 int data_len)
1158{
1159 int ret;
1160
1161 cds_ssr_protect(__func__);
1162 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1163 cds_ssr_unprotect(__func__);
1164
1165 return ret;
1166}
1167
1168/**
1169 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1170 *
1171 * @adapter: SAP adapter pointer
1172 *
1173 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1174 * radio. So in case of DFS MCC scenario override current SAP given config
1175 * to follow concurrent SAP DFS config
1176 *
1177 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1178 */
1179
1180#ifdef WLAN_FEATURE_MBSSID
1181int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1182{
1183 hdd_adapter_t *con_sap_adapter;
1184 tsap_Config_t *sap_config, *con_sap_config;
1185 int con_ch;
1186
1187 /*
1188 * Check if AP+AP case, once primary AP chooses a DFS
1189 * channel secondary AP should always follow primary APs channel
1190 */
1191 if (!cds_concurrent_beaconing_sessions_running())
1192 return 0;
1193
1194 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1195 if (!con_sap_adapter)
1196 return 0;
1197
1198 sap_config = &adapter->sessionCtx.ap.sapConfig;
1199 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1200 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1201
1202 if (!CDS_IS_DFS_CH(con_ch))
1203 return 0;
1204
1205 hddLog(LOGE, FL("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)"),
1206 sap_config->channel, con_ch);
1207 hddLog(LOG1, FL("Overriding guest AP's channel"));
1208 sap_config->channel = con_ch;
1209
1210 if (con_sap_config->acs_cfg.acs_mode == true) {
1211 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1212 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
1213 hddLog(LOGE, FL("Primary AP channel config error"));
1214 hddLog(LOGE, FL("Operating ch: %d ACS ch: %d %d"),
1215 con_ch, con_sap_config->acs_cfg.pri_ch,
1216 con_sap_config->acs_cfg.ht_sec_ch);
1217 return -EINVAL;
1218 }
1219 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1220 * MCC restriction. So free ch list allocated in do_acs
1221 * func for Sec AP and realloc for Pri AP ch list size
1222 */
1223 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301224 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301226 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 &con_sap_config->acs_cfg,
1228 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301229 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 sizeof(uint8_t) *
1231 con_sap_config->acs_cfg.ch_list_count);
1232 if (!sap_config->acs_cfg.ch_list) {
1233 hddLog(LOGE, FL("ACS config alloc fail"));
1234 return -ENOMEM;
1235 }
1236
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301237 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 con_sap_config->acs_cfg.ch_list,
1239 con_sap_config->acs_cfg.ch_list_count);
1240
1241 } else {
1242 sap_config->acs_cfg.pri_ch = con_ch;
1243 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1244 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1245 }
1246
1247 return con_ch;
1248}
1249#else
1250int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1251{
1252 return 0;
1253}
1254#endif
1255
1256/**
1257 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1258 * @sap_cfg: pointer to SAP config struct
1259 *
1260 * This function sets the default ACS start and end channel for the given band
1261 * and also parses the given ACS channel list.
1262 *
1263 * Return: None
1264 */
1265
1266static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1267 bool vht_enabled)
1268{
1269 int i;
1270 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1271 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001272 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1273 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1275 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001276 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1277 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001278 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1279 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001280 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1281 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1283 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001284 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1285 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286 }
1287
1288 if (ht_enabled)
1289 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1290
1291 if (vht_enabled)
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1293
1294
1295 /* Parse ACS Chan list from hostapd */
1296 if (!sap_cfg->acs_cfg.ch_list)
1297 return;
1298
1299 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1300 sap_cfg->acs_cfg.end_ch =
1301 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1302 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
1303 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i])
1304 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1305 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1306 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1307 }
1308}
1309
1310
1311static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1312
1313/**
1314 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1315 * @adapter: pointer to SAP adapter struct
1316 *
1317 * This function starts the ACS procedure if there are no
1318 * constraints like MBSSID DFS restrictions.
1319 *
1320 * Return: Status of ACS Start procedure
1321 */
1322
1323static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1324{
1325
1326 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1327 tsap_Config_t *sap_config;
1328 tpWLAN_SAPEventCB acs_event_callback;
1329 int status;
1330
1331 sap_config = &adapter->sessionCtx.ap.sapConfig;
1332 sap_config->channel = AUTO_CHANNEL_SELECT;
1333
1334 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1335 if (status < 0) {
1336 return status;
1337 } else {
1338 if (status > 0) {
1339 /*notify hostapd about channel override */
1340 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1341 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1342 return 0;
1343 }
1344 }
1345 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1346 if (status) {
1347 hddLog(LOGE, FL("ACS config failed"));
1348 return -EINVAL;
1349 }
1350
1351 acs_event_callback = hdd_hostapd_sap_event_cb;
1352
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301353 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301354 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355 hddLog(LOG1, FL("ACS Started for wlan%d"), adapter->dev->ifindex);
1356 status = wlansap_acs_chselect(
1357#ifdef WLAN_FEATURE_MBSSID
1358 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
1359#else
1360 hdd_ctx->pcds_context,
1361#endif
1362 acs_event_callback, sap_config, adapter->dev);
1363
1364
1365 if (status) {
1366 hddLog(LOGE, FL("ACS channel select failed"));
1367 return -EINVAL;
1368 }
1369 sap_config->acs_cfg.acs_mode = true;
1370 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1371
1372 return 0;
1373}
1374
1375/**
1376 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1377 * @wiphy: Linux wiphy struct pointer
1378 * @wdev: Linux wireless device struct pointer
1379 * @data: ACS information from hostapd
1380 * @data_len: ACS information length
1381 *
1382 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1383 * and starts ACS procedure.
1384 *
1385 * Return: ACS procedure start status
1386 */
1387
1388static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1389 struct wireless_dev *wdev,
1390 const void *data, int data_len)
1391{
1392 struct net_device *ndev = wdev->netdev;
1393 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1394 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1395 tsap_Config_t *sap_config;
1396 struct sk_buff *temp_skbuff;
1397 int status = -EINVAL, i = 0;
1398 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1399 bool ht_enabled, ht40_enabled, vht_enabled;
1400 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301401 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001402
1403 /* ***Note*** Donot set SME config related to ACS operation here because
1404 * ACS operation is not synchronouse and ACS for Second AP may come when
1405 * ACS operation for first AP is going on. So only do_acs is split to
1406 * seperate start_acs routine. Also SME-PMAC struct that is used to
1407 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1408 * config shall be set only from start_acs.
1409 */
1410
1411 /* nla_policy Policy template. Policy not applied as some attributes are
1412 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1413 *
1414 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1415 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1416 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1417 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1418 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1419 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1420 */
1421
Jeff Johnson1f61b612016-02-12 16:28:33 -08001422 ENTER_DEV(ndev);
1423
Anurag Chouhan6d760662016-02-20 16:05:43 +05301424 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425 hdd_err("Command not allowed in FTM mode");
1426 return -EPERM;
1427 }
1428
1429 if (hdd_ctx->config->force_sap_acs) {
1430 hddLog(LOGE, FL("Hostapd ACS rejected as Driver ACS enabled"));
1431 return -EPERM;
1432 }
1433
1434 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301435 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301439 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440
1441 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1442 NULL);
1443 if (status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301444 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid ATTR"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001445 goto out;
1446 }
1447
1448 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301449 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Attr hw_mode failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 goto out;
1451 }
1452 sap_config->acs_cfg.hw_mode = nla_get_u8(
1453 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1454
1455 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1456 ht_enabled =
1457 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1458 else
1459 ht_enabled = 0;
1460
1461 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1462 ht40_enabled =
1463 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1464 else
1465 ht40_enabled = 0;
1466
1467 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1468 vht_enabled =
1469 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1470 else
1471 vht_enabled = 0;
1472
1473 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1474 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1475 } else {
1476 if (ht_enabled && ht40_enabled)
1477 ch_width = 40;
1478 else
1479 ch_width = 20;
1480 }
1481 if (ch_width == 80)
1482 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1483 else if (ch_width == 40)
1484 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1485 else
1486 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1487
1488 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1489 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1490 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1491 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1492 * since it contains the frequency values of the channels in
1493 * the channel list.
1494 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1495 * is present
1496 */
1497 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1498 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1499 sap_config->acs_cfg.ch_list_count = nla_len(
1500 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1501 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301502 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503 sizeof(uint8_t) *
1504 sap_config->acs_cfg.ch_list_count);
1505 if (sap_config->acs_cfg.ch_list == NULL)
1506 goto out;
1507
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301508 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001509 sap_config->acs_cfg.ch_list_count);
1510 }
1511 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1512 uint32_t *freq =
1513 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1514 sap_config->acs_cfg.ch_list_count = nla_len(
1515 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1516 sizeof(uint32_t);
1517 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301518 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 sap_config->acs_cfg.ch_list_count);
1520 if (sap_config->acs_cfg.ch_list == NULL) {
1521 hddLog(LOGE, FL("ACS config alloc fail"));
1522 status = -ENOMEM;
1523 goto out;
1524 }
1525
1526 /* convert frequency to channel */
1527 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1528 sap_config->acs_cfg.ch_list[i] =
1529 ieee80211_frequency_to_channel(freq[i]);
1530 }
1531 }
1532
1533 hdd_debug("get pcl for DO_ACS vendor command");
1534
1535 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001536 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301537 sap_config->acs_cfg.pcl_channels,
1538 &sap_config->acs_cfg.pcl_ch_count,
1539 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301540 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 hddLog(LOGE, FL("Get PCL failed"));
1542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543 /* ACS override for android */
1544 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
1545 hddLog(LOG1, FL("ACS Config override for 11AC"));
1546 vht_enabled = 1;
1547 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1548 sap_config->acs_cfg.ch_width =
1549 hdd_ctx->config->vhtChannelWidth;
1550 /* No VHT80 in 2.4G so perform ACS accordingly */
1551 if (sap_config->acs_cfg.end_ch <= 14 &&
1552 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1553 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1554 }
1555
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301556 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 hddLog(LOG1, FL("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d"),
1559 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1560 ch_width, ht_enabled, vht_enabled,
1561 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1562
1563 if (sap_config->acs_cfg.ch_list_count) {
1564 hddLog(LOG1, FL("ACS channel list: len: %d"),
1565 sap_config->acs_cfg.ch_list_count);
1566 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1567 hddLog(LOG1, "%d ", sap_config->acs_cfg.ch_list[i]);
1568 }
1569 sap_config->acs_cfg.acs_mode = true;
1570 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
1571 /* ***Note*** Completion variable usage is not allowed here since
1572 * ACS scan operation may take max 2.2 sec for 5G band.
1573 * 9 Active channel X 40 ms active scan time +
1574 * 16 Passive channel X 110ms passive scan time
1575 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1576 * for this long. So we split up the scanning part.
1577 */
1578 set_bit(ACS_PENDING, &adapter->event_flags);
1579 hddLog(LOG1, FL("ACS Pending for wlan%d"),
1580 adapter->dev->ifindex);
1581 status = 0;
1582 } else {
1583 status = wlan_hdd_cfg80211_start_acs(adapter);
1584 }
1585
1586out:
1587 if (0 == status) {
1588 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1589 NLMSG_HDRLEN);
1590 if (temp_skbuff != NULL)
1591 return cfg80211_vendor_cmd_reply(temp_skbuff);
1592 }
1593
1594 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1595
1596 return status;
1597}
1598
1599 /**
1600 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1601 * @wiphy: Linux wiphy struct pointer
1602 * @wdev: Linux wireless device struct pointer
1603 * @data: ACS information from hostapd
1604 * @data_len: ACS information len
1605 *
1606 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1607 * and starts ACS procedure.
1608 *
1609 * Return: ACS procedure start status
1610 */
1611
1612static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1613 struct wireless_dev *wdev,
1614 const void *data, int data_len)
1615{
1616 int ret;
1617
1618 cds_ssr_protect(__func__);
1619 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1620 cds_ssr_unprotect(__func__);
1621
1622 return ret;
1623}
1624
1625/**
1626 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1627 * @work: Linux workqueue struct pointer for ACS work
1628 *
1629 * This function starts the ACS procedure which was marked pending when an ACS
1630 * procedure was in progress for a concurrent SAP interface.
1631 *
1632 * Return: None
1633 */
1634
1635static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1636{
1637 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1638 acs_pending_work.work);
1639 wlan_hdd_cfg80211_start_acs(adapter);
1640}
1641
1642/**
1643 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1644 * @adapter: Pointer to SAP adapter struct
1645 * @pri_channel: SAP ACS procedure selected Primary channel
1646 * @sec_channel: SAP ACS procedure selected secondary channel
1647 *
1648 * This is a callback function from SAP module on ACS procedure is completed.
1649 * This function send the ACS selected channel information to hostapd
1650 *
1651 * Return: None
1652 */
1653
1654void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1655{
1656 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1657 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1658 struct sk_buff *vendor_event;
1659 int ret_val;
1660 hdd_adapter_t *con_sap_adapter;
1661 uint16_t ch_width;
1662
1663 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001664 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001665 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1666 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1667 GFP_KERNEL);
1668
1669 if (!vendor_event) {
1670 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
1671 return;
1672 }
1673
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001674 ret_val = nla_put_u8(vendor_event,
1675 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1676 sap_cfg->acs_cfg.pri_ch);
1677 if (ret_val) {
1678 hddLog(LOGE,
1679 FL("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail"));
1680 kfree_skb(vendor_event);
1681 return;
1682 }
1683
1684 ret_val = nla_put_u8(vendor_event,
1685 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1686 sap_cfg->acs_cfg.ht_sec_ch);
1687 if (ret_val) {
1688 hddLog(LOGE,
1689 FL(
1690 "QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail"));
1691 kfree_skb(vendor_event);
1692 return;
1693 }
1694
1695 ret_val = nla_put_u8(vendor_event,
1696 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1697 sap_cfg->acs_cfg.vht_seg0_center_ch);
1698 if (ret_val) {
1699 hddLog(LOGE,
1700 FL(
1701 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail"));
1702 kfree_skb(vendor_event);
1703 return;
1704 }
1705
1706 ret_val = nla_put_u8(vendor_event,
1707 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1708 sap_cfg->acs_cfg.vht_seg1_center_ch);
1709 if (ret_val) {
1710 hddLog(LOGE,
1711 FL(
1712 "QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail"));
1713 kfree_skb(vendor_event);
1714 return;
1715 }
1716
1717 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1718 ch_width = 80;
1719 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1720 ch_width = 40;
1721 else
1722 ch_width = 20;
1723
1724 ret_val = nla_put_u16(vendor_event,
1725 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1726 ch_width);
1727 if (ret_val) {
1728 hddLog(LOGE,
1729 FL(
1730 "QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail"));
1731 kfree_skb(vendor_event);
1732 return;
1733 }
1734 if (sap_cfg->acs_cfg.pri_ch > 14)
1735 ret_val = nla_put_u8(vendor_event,
1736 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1737 QCA_ACS_MODE_IEEE80211A);
1738 else
1739 ret_val = nla_put_u8(vendor_event,
1740 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1741 QCA_ACS_MODE_IEEE80211G);
1742
1743 if (ret_val) {
1744 hddLog(LOGE,
1745 FL(
1746 "QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail"));
1747 kfree_skb(vendor_event);
1748 return;
1749 }
1750
1751 hddLog(LOG1,
1752 FL("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d"),
1753 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1754 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1755 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1756
1757 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1758 /* ***Note*** As already mentioned Completion variable usage is not
1759 * allowed here since ACS scan operation may take max 2.2 sec.
1760 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1761 * operation.
1762 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1763 * when Primary AP ACS is complete and secondary AP ACS is started here
1764 * immediately, Primary AP start_bss may come inbetween ACS operation
1765 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1766 * delay. This path and below constraint will be removed on sessionizing
1767 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1768 * As per design constraint user space control application must take
1769 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1770 * this code path. Sec AP hostapd should be started after Primary AP
1771 * start beaconing which can be confirmed by getchannel iwpriv command
1772 */
1773
1774 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1775 if (con_sap_adapter &&
1776 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1778 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 /* Lets give 500ms for OBSS + START_BSS to complete */
1780 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1781 msecs_to_jiffies(500));
1782 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1783 }
1784
1785 return;
1786}
1787
1788static int
1789__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1790 struct wireless_dev *wdev,
1791 const void *data,
1792 int data_len)
1793{
1794 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1795 struct sk_buff *skb = NULL;
1796 uint32_t fset = 0;
1797 int ret;
1798
Jeff Johnson1f61b612016-02-12 16:28:33 -08001799 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301800
Anurag Chouhan6d760662016-02-20 16:05:43 +05301801 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001802 hdd_err("Command not allowed in FTM mode");
1803 return -EPERM;
1804 }
1805
1806 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301807 if (ret)
1808 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809
1810 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
1811 hddLog(LOG1, FL("Infra Station mode is supported by driver"));
1812 fset |= WIFI_FEATURE_INFRA;
1813 }
1814 if (true == hdd_is_5g_supported(pHddCtx)) {
1815 hddLog(LOG1, FL("INFRA_5G is supported by firmware"));
1816 fset |= WIFI_FEATURE_INFRA_5G;
1817 }
1818#ifdef WLAN_FEATURE_P2P
1819 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1820 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
1821 hddLog(LOG1, FL("WiFi-Direct is supported by driver"));
1822 fset |= WIFI_FEATURE_P2P;
1823 }
1824#endif
1825 fset |= WIFI_FEATURE_SOFT_AP;
1826
1827 /* HOTSPOT is a supplicant feature, enable it by default */
1828 fset |= WIFI_FEATURE_HOTSPOT;
1829
1830#ifdef FEATURE_WLAN_EXTSCAN
1831 if (sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
1832 hddLog(LOG1, FL("EXTScan is supported by firmware"));
1833 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1834 }
1835#endif
1836 if (wlan_hdd_nan_is_supported()) {
1837 hddLog(LOG1, FL("NAN is supported by firmware"));
1838 fset |= WIFI_FEATURE_NAN;
1839 }
1840 if (sme_is_feature_supported_by_fw(RTT)) {
1841 hddLog(LOG1, FL("RTT is supported by firmware"));
1842 fset |= WIFI_FEATURE_D2D_RTT;
1843 fset |= WIFI_FEATURE_D2AP_RTT;
1844 }
1845#ifdef FEATURE_WLAN_SCAN_PNO
1846 if (pHddCtx->config->configPNOScanSupport &&
1847 sme_is_feature_supported_by_fw(PNO)) {
1848 hddLog(LOG1, FL("PNO is supported by firmware"));
1849 fset |= WIFI_FEATURE_PNO;
1850 }
1851#endif
1852 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1853#ifdef FEATURE_WLAN_TDLS
1854 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1855 sme_is_feature_supported_by_fw(TDLS)) {
1856 hddLog(LOG1, FL("TDLS is supported by firmware"));
1857 fset |= WIFI_FEATURE_TDLS;
1858 }
1859 if (sme_is_feature_supported_by_fw(TDLS) &&
1860 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1861 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
1862 hddLog(LOG1, FL("TDLS off-channel is supported by firmware"));
1863 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1864 }
1865#endif
1866#ifdef WLAN_AP_STA_CONCURRENCY
1867 fset |= WIFI_FEATURE_AP_STA;
1868#endif
1869 fset |= WIFI_FEATURE_RSSI_MONITOR;
1870
1871 if (hdd_link_layer_stats_supported())
1872 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1873
1874 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1875 NLMSG_HDRLEN);
1876 if (!skb) {
1877 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
1878 return -EINVAL;
1879 }
1880 hddLog(LOG1, FL("Supported Features : 0x%x"), fset);
1881 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
1882 hddLog(LOGE, FL("nla put fail"));
1883 goto nla_put_failure;
1884 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301885 ret = cfg80211_vendor_cmd_reply(skb);
1886 EXIT();
1887 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888nla_put_failure:
1889 kfree_skb(skb);
1890 return -EINVAL;
1891}
1892
1893/**
1894 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1895 * @wiphy: pointer to wireless wiphy structure.
1896 * @wdev: pointer to wireless_dev structure.
1897 * @data: Pointer to the data to be passed via vendor interface
1898 * @data_len:Length of the data to be passed
1899 *
1900 * Return: Return the Success or Failure code.
1901 */
1902static int
1903wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1904 struct wireless_dev *wdev,
1905 const void *data, int data_len)
1906{
1907 int ret = 0;
1908
1909 cds_ssr_protect(__func__);
1910 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1911 data, data_len);
1912 cds_ssr_unprotect(__func__);
1913
1914 return ret;
1915}
1916
1917/**
1918 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1919 * @wiphy: pointer to wireless wiphy structure.
1920 * @wdev: pointer to wireless_dev structure.
1921 * @data: Pointer to the data to be passed via vendor interface
1922 * @data_len:Length of the data to be passed
1923 *
1924 * Set the MAC address that is to be used for scanning.
1925 *
1926 * Return: Return the Success or Failure code.
1927 */
1928static int
1929__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1930 struct wireless_dev *wdev,
1931 const void *data,
1932 int data_len)
1933{
1934 tpSirScanMacOui pReqMsg = NULL;
1935 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1936 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301937 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001938 int ret;
1939
Jeff Johnson1f61b612016-02-12 16:28:33 -08001940 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941
Anurag Chouhan6d760662016-02-20 16:05:43 +05301942 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 hdd_err("Command not allowed in FTM mode");
1944 return -EPERM;
1945 }
1946
1947 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301948 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950
1951 if (false == pHddCtx->config->enable_mac_spoofing) {
1952 hddLog(LOGW, FL("MAC address spoofing is not enabled"));
1953 return -ENOTSUPP;
1954 }
1955
1956 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1957 data, data_len, NULL)) {
1958 hddLog(LOGE, FL("Invalid ATTR"));
1959 return -EINVAL;
1960 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301961 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 if (!pReqMsg) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301963 hddLog(LOGE, FL("qdf_mem_malloc failed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 return -ENOMEM;
1965 }
1966 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
1967 hddLog(LOGE, FL("attr mac oui failed"));
1968 goto fail;
1969 }
1970 nla_memcpy(&pReqMsg->oui[0],
1971 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1972 sizeof(pReqMsg->oui));
1973 hddLog(LOG1, FL("Oui (%02x:%02x:%02x)"), pReqMsg->oui[0],
1974 pReqMsg->oui[1], pReqMsg->oui[2]);
1975 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301976 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301977 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 FL("sme_set_scanning_mac_oui failed(err=%d)"), status);
1979 goto fail;
1980 }
1981 return 0;
1982fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301983 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 return -EINVAL;
1985}
1986
1987/**
1988 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1989 * @wiphy: pointer to wireless wiphy structure.
1990 * @wdev: pointer to wireless_dev structure.
1991 * @data: Pointer to the data to be passed via vendor interface
1992 * @data_len:Length of the data to be passed
1993 *
1994 * Set the MAC address that is to be used for scanning. This is an
1995 * SSR-protecting wrapper function.
1996 *
1997 * Return: Return the Success or Failure code.
1998 */
1999static int
2000wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2001 struct wireless_dev *wdev,
2002 const void *data,
2003 int data_len)
2004{
2005 int ret;
2006
2007 cds_ssr_protect(__func__);
2008 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2009 data, data_len);
2010 cds_ssr_unprotect(__func__);
2011
2012 return ret;
2013}
2014
2015/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302016 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2017 * @wiphy: pointer phy adapter
2018 * @wdev: pointer to wireless device structure
2019 * @data: pointer to data buffer
2020 * @data_len: length of data
2021 *
2022 * This routine will give concurrency matrix
2023 *
2024 * Return: int status code
2025 */
2026static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2027 struct wireless_dev *wdev,
2028 const void *data,
2029 int data_len)
2030{
2031 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2032 uint8_t i, feature_sets, max_feature_sets;
2033 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2034 struct sk_buff *reply_skb;
2035 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2036 int ret;
2037
2038 ENTER_DEV(wdev->netdev);
2039
2040 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2041 hdd_err("Command not allowed in FTM mode");
2042 return -EPERM;
2043 }
2044
2045 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302046 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302047 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302048
2049 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2050 data, data_len, NULL)) {
2051 hdd_err("Invalid ATTR");
2052 return -EINVAL;
2053 }
2054
2055 /* Parse and fetch max feature set */
2056 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2057 hdd_err("Attr max feature set size failed");
2058 return -EINVAL;
2059 }
2060 max_feature_sets = nla_get_u32(tb[
2061 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2062 hdd_info("Max feature set size: %d", max_feature_sets);
2063
2064 /* Fill feature combination matrix */
2065 feature_sets = 0;
2066 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2067 WIFI_FEATURE_P2P;
2068 /* Add more feature combinations here */
2069
2070 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2071 hdd_info("Number of feature sets:%d", feature_sets);
2072 hdd_info("Feature set matrix");
2073 for (i = 0; i < feature_sets; i++)
2074 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2075
2076 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2077 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2078 if (!reply_skb) {
2079 hdd_err("Feature set matrix: buffer alloc fail");
2080 return -ENOMEM;
2081 }
2082
2083 if (nla_put_u32(reply_skb,
2084 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2085 feature_sets) ||
2086 nla_put(reply_skb,
2087 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2088 sizeof(u32) * feature_sets,
2089 feature_set_matrix)) {
2090 hdd_err("nla put fail");
2091 kfree_skb(reply_skb);
2092 return -EINVAL;
2093 }
2094 return cfg80211_vendor_cmd_reply(reply_skb);
2095}
2096
2097/**
2098 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2099 * @wiphy: pointer to wireless wiphy structure.
2100 * @wdev: pointer to wireless_dev structure.
2101 * @data: Pointer to the data to be passed via vendor interface
2102 * @data_len:Length of the data to be passed
2103 *
2104 * Retrieves the concurrency feature set matrix
2105 *
2106 * Return: 0 on success, negative errno on failure
2107 */
2108static int
2109wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2110 struct wireless_dev *wdev,
2111 const void *data,
2112 int data_len)
2113{
2114 int ret;
2115
2116 cds_ssr_protect(__func__);
2117 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2118 data, data_len);
2119 cds_ssr_unprotect(__func__);
2120
2121 return ret;
2122}
2123
2124/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002125 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2126 * @feature_flags: pointer to the byte array of features.
2127 * @feature: Feature to be turned ON in the byte array.
2128 *
2129 * Return: None
2130 *
2131 * This is called to turn ON or SET the feature flag for the requested feature.
2132 **/
2133#define NUM_BITS_IN_BYTE 8
2134void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2135{
2136 uint32_t index;
2137 uint8_t bit_mask;
2138
2139 index = feature / NUM_BITS_IN_BYTE;
2140 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2141 feature_flags[index] |= bit_mask;
2142}
2143
2144/**
2145 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2146 * @wiphy: pointer to wireless wiphy structure.
2147 * @wdev: pointer to wireless_dev structure.
2148 * @data: Pointer to the data to be passed via vendor interface
2149 * @data_len:Length of the data to be passed
2150 *
2151 * This is called when wlan driver needs to send supported feature set to
2152 * supplicant upon a request/query from the supplicant.
2153 *
2154 * Return: Return the Success or Failure code.
2155 **/
2156#define MAX_CONCURRENT_CHAN_ON_24G 2
2157#define MAX_CONCURRENT_CHAN_ON_5G 2
2158static int
2159__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2160 struct wireless_dev *wdev,
2161 const void *data, int data_len)
2162{
2163 struct sk_buff *skb = NULL;
2164 uint32_t dbs_capability = 0;
2165 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302166 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167 int ret_val;
2168
2169 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2170 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2171
Jeff Johnson1f61b612016-02-12 16:28:33 -08002172 ENTER_DEV(wdev->netdev);
2173
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2175 if (ret_val)
2176 return ret_val;
2177
Anurag Chouhan6d760662016-02-20 16:05:43 +05302178 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 hdd_err("Command not allowed in FTM mode");
2180 return -EPERM;
2181 }
2182
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002183 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 hddLog(LOG1, FL("Key Mgmt Offload is supported"));
2185 wlan_hdd_cfg80211_set_feature(feature_flags,
2186 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2187 }
2188
2189 wlan_hdd_cfg80211_set_feature(feature_flags,
2190 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2191 if (wma_is_scan_simultaneous_capable())
2192 wlan_hdd_cfg80211_set_feature(feature_flags,
2193 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
2194 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2195 NLMSG_HDRLEN);
2196
2197 if (!skb) {
2198 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
2199 return -ENOMEM;
2200 }
2201
2202 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2203 sizeof(feature_flags), feature_flags))
2204 goto nla_put_failure;
2205
2206 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302207 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 if (one_by_one_dbs)
2209 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2210
2211 if (two_by_two_dbs)
2212 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2213
2214 if (!one_by_one_dbs && !two_by_two_dbs)
2215 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2216 } else {
2217 hdd_err("wma_get_dbs_hw_mode failed");
2218 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2219 }
2220
2221 hdd_info("dbs_capability is %d", dbs_capability);
2222
2223 if (nla_put_u32(skb,
2224 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2225 MAX_CONCURRENT_CHAN_ON_24G))
2226 goto nla_put_failure;
2227
2228 if (nla_put_u32(skb,
2229 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2230 MAX_CONCURRENT_CHAN_ON_5G))
2231 goto nla_put_failure;
2232
2233 return cfg80211_vendor_cmd_reply(skb);
2234
2235nla_put_failure:
2236 kfree_skb(skb);
2237 return -EINVAL;
2238}
2239
2240/**
2241 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2242 * @wiphy: pointer to wireless wiphy structure.
2243 * @wdev: pointer to wireless_dev structure.
2244 * @data: Pointer to the data to be passed via vendor interface
2245 * @data_len:Length of the data to be passed
2246 *
2247 * This is called when wlan driver needs to send supported feature set to
2248 * supplicant upon a request/query from the supplicant.
2249 *
2250 * Return: Return the Success or Failure code.
2251 */
2252static int
2253wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2254 struct wireless_dev *wdev,
2255 const void *data, int data_len)
2256{
2257 int ret;
2258
2259 cds_ssr_protect(__func__);
2260 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2261 data, data_len);
2262 cds_ssr_unprotect(__func__);
2263
2264 return ret;
2265}
2266
2267
2268/**
2269 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2270 * @wiphy: The wiphy structure
2271 * @wdev: The wireless device
2272 * @data: Data passed by framework
2273 * @data_len: Parameters to be configured passed as data
2274 *
2275 * The roaming related parameters are configured by the framework
2276 * using this interface.
2277 *
2278 * Return: Return either success or failure code.
2279 */
2280static int
2281__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2282 struct wireless_dev *wdev, const void *data, int data_len)
2283{
2284 struct net_device *dev = wdev->netdev;
2285 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2286 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2287 uint8_t session_id;
2288 struct roam_ext_params roam_params;
2289 uint32_t cmd_type, req_id;
2290 struct nlattr *curr_attr;
2291 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2292 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2293 int rem, i;
2294 uint32_t buf_len = 0;
2295 int ret;
2296
Jeff Johnson1f61b612016-02-12 16:28:33 -08002297 ENTER_DEV(dev);
2298
Anurag Chouhan6d760662016-02-20 16:05:43 +05302299 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002300 hdd_err("Command not allowed in FTM mode");
2301 return -EPERM;
2302 }
2303
2304 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302305 if (ret)
2306 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307
2308 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2309 data, data_len,
2310 NULL)) {
2311 hddLog(LOGE, FL("Invalid ATTR"));
2312 return -EINVAL;
2313 }
2314 /* Parse and fetch Command Type*/
2315 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
2316 hddLog(LOGE, FL("roam cmd type failed"));
2317 goto fail;
2318 }
2319 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302320 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2322 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
2323 hddLog(LOGE, FL("attr request id failed"));
2324 goto fail;
2325 }
2326 req_id = nla_get_u32(
2327 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302328 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Req Id (%d)"), req_id);
2329 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Cmd Type (%d)"), cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 switch (cmd_type) {
2331 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2332 i = 0;
2333 nla_for_each_nested(curr_attr,
2334 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2335 rem) {
2336 if (nla_parse(tb2,
2337 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2338 nla_data(curr_attr), nla_len(curr_attr),
2339 NULL)) {
2340 hddLog(LOGE,
2341 FL("nla_parse failed"));
2342 goto fail;
2343 }
2344 /* Parse and Fetch allowed SSID list*/
2345 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
2346 hddLog(LOGE, FL("attr allowed ssid failed"));
2347 goto fail;
2348 }
2349 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2350 /*
2351 * Upper Layers include a null termination character.
2352 * Check for the actual permissible length of SSID and
2353 * also ensure not to copy the NULL termination
2354 * character to the driver buffer.
2355 */
2356 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2357 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2358 nla_memcpy(
2359 roam_params.ssid_allowed_list[i].ssId,
2360 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2361 buf_len - 1);
2362 roam_params.ssid_allowed_list[i].length =
2363 buf_len - 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302364 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 FL("SSID[%d]: %.*s,length = %d"), i,
2366 roam_params.ssid_allowed_list[i].length,
2367 roam_params.ssid_allowed_list[i].ssId,
2368 roam_params.ssid_allowed_list[i].length);
2369 i++;
2370 } else {
2371 hddLog(LOGE, FL("Invalid buffer length"));
2372 }
2373 }
2374 roam_params.num_ssid_allowed_list = i;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302375 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Allowed SSID %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 roam_params.num_ssid_allowed_list);
2377 sme_update_roam_params(pHddCtx->hHal, session_id,
2378 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2379 break;
2380 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2381 /* Parse and fetch 5G Boost Threshold */
2382 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
2383 hddLog(LOGE, FL("5G boost threshold failed"));
2384 goto fail;
2385 }
2386 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2387 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302388 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389 roam_params.raise_rssi_thresh_5g);
2390 /* Parse and fetch 5G Penalty Threshold */
2391 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
2392 hddLog(LOGE, FL("5G penalty threshold failed"));
2393 goto fail;
2394 }
2395 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2396 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302397 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398 roam_params.drop_rssi_thresh_5g);
2399 /* Parse and fetch 5G Boost Factor */
2400 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
2401 hddLog(LOGE, FL("5G boost Factor failed"));
2402 goto fail;
2403 }
2404 roam_params.raise_factor_5g = nla_get_u32(
2405 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302406 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Boost Factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002407 roam_params.raise_factor_5g);
2408 /* Parse and fetch 5G Penalty factor */
2409 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
2410 hddLog(LOGE, FL("5G Penalty Factor failed"));
2411 goto fail;
2412 }
2413 roam_params.drop_factor_5g = nla_get_u32(
2414 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302415 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Penalty factor (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416 roam_params.drop_factor_5g);
2417 /* Parse and fetch 5G Max Boost */
2418 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
2419 hddLog(LOGE, FL("5G Max Boost failed"));
2420 goto fail;
2421 }
2422 roam_params.max_raise_rssi_5g = nla_get_u32(
2423 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302424 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("5G Max Boost (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 roam_params.max_raise_rssi_5g);
2426 /* Parse and fetch Rssi Diff */
2427 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
2428 hddLog(LOGE, FL("Rssi Diff failed"));
2429 goto fail;
2430 }
2431 roam_params.rssi_diff = nla_get_s32(
2432 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302433 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("RSSI Diff (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 roam_params.rssi_diff);
2435 /* Parse and fetch Alert Rssi Threshold */
2436 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
2437 hddLog(LOGE, FL("Alert Rssi Threshold failed"));
2438 goto fail;
2439 }
2440 roam_params.alert_rssi_threshold = nla_get_u32(
2441 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302442 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Alert RSSI Threshold (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 roam_params.alert_rssi_threshold);
2444 sme_update_roam_params(pHddCtx->hHal, session_id,
2445 roam_params,
2446 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2447 break;
2448 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2449 /* Parse and fetch Activate Good Rssi Roam */
2450 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
2451 hddLog(LOGE, FL("Activate Good Rssi Roam failed"));
2452 goto fail;
2453 }
2454 roam_params.good_rssi_roam = nla_get_s32(
2455 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302456 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Activate Good Rssi Roam (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 roam_params.good_rssi_roam);
2458 sme_update_roam_params(pHddCtx->hHal, session_id,
2459 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2460 break;
2461 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2462 /* Parse and fetch number of preferred BSSID */
2463 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
2464 hddLog(LOGE, FL("attr num of preferred bssid failed"));
2465 goto fail;
2466 }
2467 roam_params.num_bssid_favored = nla_get_u32(
2468 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302469 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of Preferred BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 roam_params.num_bssid_favored);
2471 i = 0;
2472 nla_for_each_nested(curr_attr,
2473 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2474 rem) {
2475 if (nla_parse(tb2,
2476 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2477 nla_data(curr_attr), nla_len(curr_attr),
2478 NULL)) {
2479 hddLog(LOGE, FL("nla_parse failed"));
2480 goto fail;
2481 }
2482 /* Parse and fetch MAC address */
2483 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
2484 hddLog(LOGE, FL("attr mac address failed"));
2485 goto fail;
2486 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002487 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302489 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002490 hdd_debug(MAC_ADDRESS_STR,
2491 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492 /* Parse and fetch preference factor*/
2493 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
2494 hddLog(LOGE, FL("BSSID Preference score failed"));
2495 goto fail;
2496 }
2497 roam_params.bssid_favored_factor[i] = nla_get_u32(
2498 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302499 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("BSSID Preference score (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500 roam_params.bssid_favored_factor[i]);
2501 i++;
2502 }
2503 sme_update_roam_params(pHddCtx->hHal, session_id,
2504 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2505 break;
2506 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2507 /* Parse and fetch number of blacklist BSSID */
2508 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
2509 hddLog(LOGE, FL("attr num of blacklist bssid failed"));
2510 goto fail;
2511 }
2512 roam_params.num_bssid_avoid_list = nla_get_u32(
2513 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302514 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Num of blacklist BSSID (%d)"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515 roam_params.num_bssid_avoid_list);
2516 i = 0;
2517 nla_for_each_nested(curr_attr,
2518 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2519 rem) {
2520 if (nla_parse(tb2,
2521 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2522 nla_data(curr_attr), nla_len(curr_attr),
2523 NULL)) {
2524 hddLog(LOGE, FL("nla_parse failed"));
2525 goto fail;
2526 }
2527 /* Parse and fetch MAC address */
2528 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
2529 hddLog(LOGE, FL("attr blacklist addr failed"));
2530 goto fail;
2531 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002532 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302534 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002535 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002537 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 i++;
2539 }
2540 sme_update_roam_params(pHddCtx->hHal, session_id,
2541 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2542 break;
2543 }
2544 return 0;
2545fail:
2546 return -EINVAL;
2547}
2548
2549/**
2550 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2551 * @wiphy: pointer to wireless wiphy structure.
2552 * @wdev: pointer to wireless_dev structure.
2553 * @data: Pointer to the data to be passed via vendor interface
2554 * @data_len:Length of the data to be passed
2555 *
2556 * Return: Return the Success or Failure code.
2557 */
2558static int
2559wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2560 struct wireless_dev *wdev,
2561 const void *data,
2562 int data_len)
2563{
2564 int ret;
2565
2566 cds_ssr_protect(__func__);
2567 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2568 data, data_len);
2569 cds_ssr_unprotect(__func__);
2570
2571 return ret;
2572}
2573
2574static const struct nla_policy
2575wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2576 +1] = {
2577 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2578};
2579
2580/**
2581 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2582 * @hdd_ctx: HDD context
2583 * @device_mode: device mode
2584 * Return: bool
2585 */
2586static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002587 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588{
2589 hdd_adapter_t *adapter;
2590 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2591 hdd_ap_ctx_t *ap_ctx;
2592 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302593 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302595 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596 &adapter_node);
2597
2598 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302599 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 adapter = adapter_node->pAdapter;
2601
2602 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002603 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 ap_ctx =
2605 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2606
2607 /*
2608 * if there is SAP already running on DFS channel,
2609 * do not disable scan on dfs channels. Note that
2610 * with SAP on DFS, there cannot be conurrency on
2611 * single radio. But then we can have multiple
2612 * radios !!
2613 */
2614 if (CHANNEL_STATE_DFS ==
2615 cds_get_channel_state(
2616 ap_ctx->operatingChannel)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302617 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 FL("SAP running on DFS channel"));
2619 return true;
2620 }
2621 }
2622
2623 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002624 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 sta_ctx =
2626 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2627
2628 /*
2629 * if STA is already connected on DFS channel,
2630 * do not disable scan on dfs channels
2631 */
2632 if (hdd_conn_is_connected(sta_ctx) &&
2633 (CHANNEL_STATE_DFS ==
2634 cds_get_channel_state(
2635 sta_ctx->conn_info.operationChannel))) {
2636 hddLog(LOGE,
2637 FL("client connected on DFS channel"));
2638 return true;
2639 }
2640 }
2641
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302642 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643 adapter_node,
2644 &next);
2645 adapter_node = next;
2646 }
2647
2648 return false;
2649}
2650
2651/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002652 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2653 * @hdd_ctx: HDD context within host driver
2654 * @adapter: Adapter pointer
2655 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2656 *
2657 * Loops through devices to see who is operating on DFS channels
2658 * and then disables/enables DFS channels by calling SME API.
2659 * Fails the disable request if any device is active on a DFS channel.
2660 *
2661 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002663
2664int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2665 hdd_adapter_t *adapter,
2666 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302669 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671
2672 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2673 if (no_dfs_flag) {
2674 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002675 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676
2677 if (true == status)
2678 return -EOPNOTSUPP;
2679
2680 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002681 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682
2683 if (true == status)
2684 return -EOPNOTSUPP;
2685 }
2686
2687 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2688
2689 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2690
2691 /*
2692 * call the SME API to tunnel down the new channel list
2693 * to the firmware
2694 */
2695 status = sme_handle_dfs_chan_scan(
2696 h_hal, hdd_ctx->config->enableDFSChnlScan);
2697
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302698 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 ret_val = 0;
2700
2701 /*
2702 * Clear the SME scan cache also. Note that the
2703 * clearing of scan results is independent of session;
2704 * so no need to iterate over
2705 * all sessions
2706 */
2707 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302708 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 ret_val = -EPERM;
2710 }
2711
2712 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302713 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 FL(" the DFS flag has not changed"));
2715 ret_val = 0;
2716 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002717 return ret_val;
2718}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002719
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002720/**
2721 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2722 * @wiphy: corestack handler
2723 * @wdev: wireless device
2724 * @data: data
2725 * @data_len: data length
2726 * Return: success(0) or reason code for failure
2727 */
2728static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2729 struct wireless_dev *wdev,
2730 const void *data,
2731 int data_len)
2732{
2733 struct net_device *dev = wdev->netdev;
2734 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2735 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2736 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2737 int ret_val;
2738 uint32_t no_dfs_flag = 0;
2739
Jeff Johnson1f61b612016-02-12 16:28:33 -08002740 ENTER_DEV(dev);
2741
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002742 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302743 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002744 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002745
2746 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2747 data, data_len,
2748 wlan_hdd_set_no_dfs_flag_config_policy)) {
2749 hdd_err("invalid attr");
2750 return -EINVAL;
2751 }
2752
2753 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2754 hdd_err("attr dfs flag failed");
2755 return -EINVAL;
2756 }
2757
2758 no_dfs_flag = nla_get_u32(
2759 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2760
2761 hddLog(LOG1, FL(" DFS flag = %d"), no_dfs_flag);
2762
2763 if (no_dfs_flag > 1) {
2764 hddLog(LOGE, FL("invalid value of dfs flag"));
2765 return -EINVAL;
2766 }
2767
2768 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2769 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002770 return ret_val;
2771}
2772
2773/**
2774 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2775 *
2776 * @wiphy: wiphy device pointer
2777 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002778 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 * @data_len: Buffer length
2780 *
2781 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2782 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2783 *
2784 * Return: EOK or other error codes.
2785 */
2786
2787static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2788 struct wireless_dev *wdev,
2789 const void *data,
2790 int data_len)
2791{
2792 int ret;
2793
2794 cds_ssr_protect(__func__);
2795 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2796 data, data_len);
2797 cds_ssr_unprotect(__func__);
2798
2799 return ret;
2800}
2801
Manikandan Mohan80dea792016-04-28 16:36:48 -07002802static const struct nla_policy
2803wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2804 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2805};
2806
2807/**
2808 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2809 * @wiphy: wiphy device pointer
2810 * @wdev: wireless device pointer
2811 * @data: Vendor command data buffer
2812 * @data_len: Buffer length
2813 *
2814 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2815 * setup WISA Mode features.
2816 *
2817 * Return: Success(0) or reason code for failure
2818 */
2819static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2820 struct wireless_dev *wdev, const void *data, int data_len)
2821{
2822 struct net_device *dev = wdev->netdev;
2823 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2824 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2825 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2826 struct sir_wisa_params wisa;
2827 int ret_val;
2828 QDF_STATUS status;
2829 bool wisa_mode;
2830
2831 ENTER_DEV(dev);
2832 ret_val = wlan_hdd_validate_context(hdd_ctx);
2833 if (ret_val)
2834 goto err;
2835
2836 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2837 hdd_err("Command not allowed in FTM mode");
2838 return -EPERM;
2839 }
2840
2841 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2842 wlan_hdd_wisa_cmd_policy)) {
2843 hdd_err("Invalid WISA cmd attributes");
2844 ret_val = -EINVAL;
2845 goto err;
2846 }
2847 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2848 hdd_err("Invalid WISA mode");
2849 ret_val = -EINVAL;
2850 goto err;
2851 }
2852
2853 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2854 hdd_info("WISA Mode: %d", wisa_mode);
2855 wisa.mode = wisa_mode;
2856 wisa.vdev_id = adapter->sessionId;
2857 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002858 if (!QDF_IS_STATUS_SUCCESS(status)) {
2859 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002860 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002861 }
2862 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2863 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2864 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002865err:
2866 EXIT();
2867 return ret_val;
2868}
2869
2870/**
2871 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2872 * @wiphy: corestack handler
2873 * @wdev: wireless device
2874 * @data: data
2875 * @data_len: data length
2876 *
2877 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2878 * setup WISA mode features.
2879 *
2880 * Return: Success(0) or reason code for failure
2881 */
2882static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2883 struct wireless_dev *wdev,
2884 const void *data,
2885 int data_len)
2886{
2887 int ret;
2888
2889 cds_ssr_protect(__func__);
2890 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2891 cds_ssr_unprotect(__func__);
2892
2893 return ret;
2894}
2895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002896#ifdef WLAN_FEATURE_ROAM_OFFLOAD
2897/**
2898 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2899 * @wiphy: pointer to wireless wiphy structure.
2900 * @wdev: pointer to wireless_dev structure.
2901 * @data: Pointer to the Key data
2902 * @data_len:Length of the data passed
2903 *
2904 * This is called when wlan driver needs to save the keys received via
2905 * vendor specific command.
2906 *
2907 * Return: Return the Success or Failure code.
2908 */
2909static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2910 struct wireless_dev *wdev,
2911 const void *data, int data_len)
2912{
2913 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
2914 struct net_device *dev = wdev->netdev;
2915 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
2916 hdd_context_t *hdd_ctx_ptr;
2917 int status;
2918
Jeff Johnson1f61b612016-02-12 16:28:33 -08002919 ENTER_DEV(dev);
2920
Anurag Chouhan6d760662016-02-20 16:05:43 +05302921 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 hdd_err("Command not allowed in FTM mode");
2923 return -EPERM;
2924 }
2925
2926 if ((data == NULL) || (data_len == 0) ||
2927 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
2928 hddLog(LOGE, FL("Invalid data"));
2929 return -EINVAL;
2930 }
2931
2932 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
2933 if (!hdd_ctx_ptr) {
2934 hddLog(LOGE, FL("HDD context is null"));
2935 return -EINVAL;
2936 }
2937
2938 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302939 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 return status;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
2943 hdd_adapter_ptr->sessionId,
2944 true);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302945 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
2946 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
2948 hdd_adapter_ptr->sessionId, local_pmk, data_len);
2949 return 0;
2950}
2951
2952/**
2953 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
2954 * @wiphy: pointer to wireless wiphy structure.
2955 * @wdev: pointer to wireless_dev structure.
2956 * @data: Pointer to the Key data
2957 * @data_len:Length of the data passed
2958 *
2959 * This is called when wlan driver needs to save the keys received via
2960 * vendor specific command.
2961 *
2962 * Return: Return the Success or Failure code.
2963 */
2964static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
2965 struct wireless_dev *wdev,
2966 const void *data, int data_len)
2967{
2968 int ret;
2969
2970 cds_ssr_protect(__func__);
2971 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
2972 cds_ssr_unprotect(__func__);
2973
2974 return ret;
2975}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08002976#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977
2978static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
2979 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
2980 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
2981 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07002982 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002983};
2984
2985/**
2986 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
2987 * @wiphy: pointer to wireless wiphy structure.
2988 * @wdev: pointer to wireless_dev structure.
2989 * @data: Pointer to the data to be passed via vendor interface
2990 * @data_len:Length of the data to be passed
2991 *
2992 * This is called when wlan driver needs to send wifi driver related info
2993 * (driver/fw version) to the user space application upon request.
2994 *
2995 * Return: Return the Success or Failure code.
2996 */
2997static int
2998__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
2999 struct wireless_dev *wdev,
3000 const void *data, int data_len)
3001{
3002 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3003 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003004 tSirVersionString driver_version;
3005 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003006 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003008 struct sk_buff *reply_skb;
3009 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010
Jeff Johnson1f61b612016-02-12 16:28:33 -08003011 ENTER_DEV(wdev->netdev);
3012
Anurag Chouhan6d760662016-02-20 16:05:43 +05303013 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 hdd_err("Command not allowed in FTM mode");
3015 return -EPERM;
3016 }
3017
3018 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303019 if (status)
3020 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021
3022 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3023 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003024 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003025 return -EINVAL;
3026 }
3027
3028 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003029 hdd_err("Rcvd req for Driver version");
3030 strlcpy(driver_version, QWLAN_VERSIONSTR,
3031 sizeof(driver_version));
3032 skb_len += strlen(driver_version) + 1;
3033 count++;
3034 }
3035
3036 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3037 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3039 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003040 snprintf(firmware_version, sizeof(firmware_version),
3041 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3042 skb_len += strlen(firmware_version) + 1;
3043 count++;
3044 }
3045
3046 if (count == 0) {
3047 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 return -EINVAL;
3049 }
3050
Ryan Hsu7ac88852016-04-28 10:20:34 -07003051 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3052 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3053
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003055 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 return -ENOMEM;
3057 }
3058
Ryan Hsu7ac88852016-04-28 10:20:34 -07003059 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3060 if (nla_put_string(reply_skb,
3061 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3062 driver_version))
3063 goto error_nla_fail;
3064 }
3065
3066 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3067 if (nla_put_string(reply_skb,
3068 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3069 firmware_version))
3070 goto error_nla_fail;
3071 }
3072
3073 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3074 if (nla_put_u32(reply_skb,
3075 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3076 hdd_ctx->radio_index))
3077 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 }
3079
3080 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003081
3082error_nla_fail:
3083 hdd_err("nla put fail");
3084 kfree_skb(reply_skb);
3085 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086}
3087
3088/**
3089 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3090 * @wiphy: pointer to wireless wiphy structure.
3091 * @wdev: pointer to wireless_dev structure.
3092 * @data: Pointer to the data to be passed via vendor interface
3093 * @data_len:Length of the data to be passed
3094 *
3095 * This is called when wlan driver needs to send wifi driver related info
3096 * (driver/fw version) to the user space application upon request.
3097 *
3098 * Return: Return the Success or Failure code.
3099 */
3100static int
3101wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3102 struct wireless_dev *wdev,
3103 const void *data, int data_len)
3104{
3105 int ret;
3106
3107 cds_ssr_protect(__func__);
3108 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3109 cds_ssr_unprotect(__func__);
3110
3111 return ret;
3112}
3113
3114/**
3115 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3116 * @wiphy: pointer to wireless wiphy structure.
3117 * @wdev: pointer to wireless_dev structure.
3118 * @data: Pointer to the data to be passed via vendor interface
3119 * @data_len:Length of the data to be passed
3120 *
3121 * This is called by userspace to know the supported logger features
3122 *
3123 * Return: Return the Success or Failure code.
3124 */
3125static int
3126__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3127 struct wireless_dev *wdev,
3128 const void *data, int data_len)
3129{
3130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3131 int status;
3132 uint32_t features;
3133 struct sk_buff *reply_skb = NULL;
3134
Jeff Johnson1f61b612016-02-12 16:28:33 -08003135 ENTER_DEV(wdev->netdev);
3136
Anurag Chouhan6d760662016-02-20 16:05:43 +05303137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 hdd_err("Command not allowed in FTM mode");
3139 return -EPERM;
3140 }
3141
3142 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303143 if (status)
3144 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145
3146 features = 0;
3147
3148 if (hdd_is_memdump_supported())
3149 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3150 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3151 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3152 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3153
3154 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3155 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3156 if (!reply_skb) {
3157 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3158 return -ENOMEM;
3159 }
3160
3161 hddLog(LOG1, FL("Supported logger features: 0x%0x"), features);
3162 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3163 features)) {
3164 hddLog(LOGE, FL("nla put fail"));
3165 kfree_skb(reply_skb);
3166 return -EINVAL;
3167 }
3168
3169 return cfg80211_vendor_cmd_reply(reply_skb);
3170}
3171
3172/**
3173 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3174 * @wiphy: pointer to wireless wiphy structure.
3175 * @wdev: pointer to wireless_dev structure.
3176 * @data: Pointer to the data to be passed via vendor interface
3177 * @data_len:Length of the data to be passed
3178 *
3179 * This is called by userspace to know the supported logger features
3180 *
3181 * Return: Return the Success or Failure code.
3182 */
3183static int
3184wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3185 struct wireless_dev *wdev,
3186 const void *data, int data_len)
3187{
3188 int ret;
3189
3190 cds_ssr_protect(__func__);
3191 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3192 data, data_len);
3193 cds_ssr_unprotect(__func__);
3194
3195 return ret;
3196}
3197
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003198#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199/**
3200 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3201 * @hdd_ctx_ptr: pointer to HDD Context.
3202 * @bssid: pointer to bssid of roamed AP.
3203 * @req_rsn_ie: Pointer to request RSN IE
3204 * @req_rsn_len: Length of the request RSN IE
3205 * @rsp_rsn_ie: Pointer to response RSN IE
3206 * @rsp_rsn_len: Length of the response RSN IE
3207 * @roam_info_ptr: Pointer to the roaming related information
3208 *
3209 * This is called when wlan driver needs to send the roaming and
3210 * authorization information after roaming.
3211 *
3212 * The information that would be sent is the request RSN IE, response
3213 * RSN IE and BSSID of the newly roamed AP.
3214 *
3215 * If the Authorized status is authenticated, then additional parameters
3216 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3217 * supplicant.
3218 *
3219 * The supplicant upon receiving this event would ignore the legacy
3220 * cfg80211_roamed call and use the entire information from this event.
3221 * The cfg80211_roamed should still co-exist since the kernel will
3222 * make use of the parameters even if the supplicant ignores it.
3223 *
3224 * Return: Return the Success or Failure code.
3225 */
3226int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3227 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3228 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3229{
3230 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003231 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 ENTER();
3233
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303234 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003237 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003238 !roam_info_ptr->roamSynchInProgress)
3239 return 0;
3240
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3242 NULL,
3243 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3244 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3245 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003246 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3248 GFP_KERNEL);
3249
3250 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303251 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 FL("cfg80211_vendor_event_alloc failed"));
3253 return -EINVAL;
3254 }
3255
3256 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3257 ETH_ALEN, bssid) ||
3258 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3259 req_rsn_len, req_rsn_ie) ||
3260 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3261 rsp_rsn_len, rsp_rsn_ie)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303262 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003263 goto nla_put_failure;
3264 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303265 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Auth Status = %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 roam_info_ptr->synchAuthStatus);
3267 if (roam_info_ptr->synchAuthStatus ==
3268 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303269 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's"));
Naveen Rawat14298b92015-11-25 16:27:41 -08003270 if (nla_put_u8(skb,
3271 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3272 hdd_err("nla put fail");
3273 goto nla_put_failure;
3274 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003275 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3276 /* if FT or CCKM connection: dont send replay counter */
3277 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3278 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3279 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3280 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3281 nla_put(skb,
3282 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3283 SIR_REPLAY_CTR_LEN,
3284 roam_info_ptr->replay_ctr)) {
3285 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003286 hdd_err("failed to send replay counter.");
3287 goto nla_put_failure;
3288 }
3289 if (nla_put(skb,
3290 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3291 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3292 nla_put(skb,
3293 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3294 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3295 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003296 goto nla_put_failure;
3297 }
3298 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303299 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("No Auth Params TLV's"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3301 false)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303302 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003303 goto nla_put_failure;
3304 }
3305 }
3306
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303307 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Subnet Change Status = %d"),
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003308 roam_info_ptr->subnet_change_status);
3309
3310 /*
3311 * Add subnet change status if subnet has changed
3312 * 0 = unchanged
3313 * 1 = changed
3314 * 2 = unknown
3315 */
3316 if (roam_info_ptr->subnet_change_status) {
3317 if (nla_put_u8(skb,
3318 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3319 roam_info_ptr->subnet_change_status)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303320 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla put fail"));
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003321 goto nla_put_failure;
3322 }
3323 }
3324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003325 cfg80211_vendor_event(skb, GFP_KERNEL);
3326 return 0;
3327
3328nla_put_failure:
3329 kfree_skb(skb);
3330 return -EINVAL;
3331}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003332#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003333
3334static const struct nla_policy
3335wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3336
3337 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3338 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3339 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3340};
3341
3342
3343/**
3344 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3345 * vendor command
3346 *
3347 * @wiphy: wiphy device pointer
3348 * @wdev: wireless device pointer
3349 * @data: Vendor command data buffer
3350 * @data_len: Buffer length
3351 *
3352 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3353 *
3354 * Return: Error code.
3355 */
3356static int
3357__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3358 struct wireless_dev *wdev,
3359 const void *data,
3360 int data_len)
3361{
3362 struct net_device *dev = wdev->netdev;
3363 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3364 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3365 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3366 int ret_val = 0;
3367 u32 modulated_dtim;
3368 u16 stats_avg_factor;
3369 u32 guard_time;
Krunal Sonie3531942016-04-12 17:43:53 -07003370 u32 ftm_capab;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303371 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003372
Jeff Johnson1f61b612016-02-12 16:28:33 -08003373 ENTER_DEV(dev);
3374
Anurag Chouhan6d760662016-02-20 16:05:43 +05303375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003376 hdd_err("Command not allowed in FTM mode");
3377 return -EPERM;
3378 }
3379
3380 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303381 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003382 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383
3384 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3385 data, data_len,
3386 wlan_hdd_wifi_config_policy)) {
3387 hddLog(LOGE, FL("invalid attr"));
3388 return -EINVAL;
3389 }
3390
Krunal Sonie3531942016-04-12 17:43:53 -07003391 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3392 ftm_capab = nla_get_u32(tb[
3393 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3394 hdd_ctx->config->fine_time_meas_cap =
3395 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3396 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
3397 hdd_ctx->config->fine_time_meas_cap);
3398 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3399 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3400 hdd_ctx->config->fine_time_meas_cap);
3401 }
3402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3404 modulated_dtim = nla_get_u32(
3405 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3406
3407 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3408 adapter->sessionId,
3409 modulated_dtim);
3410
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303411 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003412 ret_val = -EPERM;
3413 }
3414
3415 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3416 stats_avg_factor = nla_get_u16(
3417 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3418 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3419 adapter->sessionId,
3420 stats_avg_factor);
3421
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303422 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423 ret_val = -EPERM;
3424 }
3425
3426
3427 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3428 guard_time = nla_get_u32(
3429 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3430 status = sme_configure_guard_time(hdd_ctx->hHal,
3431 adapter->sessionId,
3432 guard_time);
3433
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303434 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003435 ret_val = -EPERM;
3436 }
3437
3438 return ret_val;
3439}
3440
3441/**
3442 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3443 * vendor command
3444 *
3445 * @wiphy: wiphy device pointer
3446 * @wdev: wireless device pointer
3447 * @data: Vendor command data buffer
3448 * @data_len: Buffer length
3449 *
3450 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3451 *
3452 * Return: EOK or other error codes.
3453 */
3454static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3455 struct wireless_dev *wdev,
3456 const void *data,
3457 int data_len)
3458{
3459 int ret;
3460
3461 cds_ssr_protect(__func__);
3462 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3463 data, data_len);
3464 cds_ssr_unprotect(__func__);
3465
3466 return ret;
3467}
3468
3469static const struct
3470nla_policy
3471qca_wlan_vendor_wifi_logger_start_policy
3472[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3473 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3474 = {.type = NLA_U32 },
3475 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3476 = {.type = NLA_U32 },
3477 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3478 = {.type = NLA_U32 },
3479};
3480
3481/**
3482 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3483 * or disable the collection of packet statistics from the firmware
3484 * @wiphy: WIPHY structure pointer
3485 * @wdev: Wireless device structure pointer
3486 * @data: Pointer to the data received
3487 * @data_len: Length of the data received
3488 *
3489 * This function enables or disables the collection of packet statistics from
3490 * the firmware
3491 *
3492 * Return: 0 on success and errno on failure
3493 */
3494static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3495 struct wireless_dev *wdev,
3496 const void *data,
3497 int data_len)
3498{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303499 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3501 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
3502 struct sir_wifi_start_log start_log;
3503
Jeff Johnson1f61b612016-02-12 16:28:33 -08003504 ENTER_DEV(wdev->netdev);
3505
Anurag Chouhan6d760662016-02-20 16:05:43 +05303506 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 hdd_err("Command not allowed in FTM mode");
3508 return -EPERM;
3509 }
3510
3511 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303512 if (status)
3513 return status;
3514
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003515
3516 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
3517 data, data_len,
3518 qca_wlan_vendor_wifi_logger_start_policy)) {
3519 hddLog(LOGE, FL("Invalid attribute"));
3520 return -EINVAL;
3521 }
3522
3523 /* Parse and fetch ring id */
3524 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
3525 hddLog(LOGE, FL("attr ATTR failed"));
3526 return -EINVAL;
3527 }
3528 start_log.ring_id = nla_get_u32(
3529 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003530 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531
3532 /* Parse and fetch verbose level */
3533 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
3534 hddLog(LOGE, FL("attr verbose_level failed"));
3535 return -EINVAL;
3536 }
3537 start_log.verbose_level = nla_get_u32(
3538 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003539 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540
3541 /* Parse and fetch flag */
3542 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
3543 hddLog(LOGE, FL("attr flag failed"));
3544 return -EINVAL;
3545 }
3546 start_log.flag = nla_get_u32(
3547 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08003548 hdd_info("flag=%d", start_log.flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549
3550 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
3551
3552 if (start_log.ring_id == RING_ID_WAKELOCK) {
3553 /* Start/stop wakelock events */
3554 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
3555 cds_set_wakelock_logging(true);
3556 else
3557 cds_set_wakelock_logging(false);
3558 return 0;
3559 }
3560
3561 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303562 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003563 hddLog(LOGE, FL("sme_wifi_start_logger failed(err=%d)"),
3564 status);
3565 return -EINVAL;
3566 }
3567 return 0;
3568}
3569
3570/**
3571 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
3572 * or disable the collection of packet statistics from the firmware
3573 * @wiphy: WIPHY structure pointer
3574 * @wdev: Wireless device structure pointer
3575 * @data: Pointer to the data received
3576 * @data_len: Length of the data received
3577 *
3578 * This function is used to enable or disable the collection of packet
3579 * statistics from the firmware
3580 *
3581 * Return: 0 on success and errno on failure
3582 */
3583static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
3584 struct wireless_dev *wdev,
3585 const void *data,
3586 int data_len)
3587{
3588 int ret = 0;
3589
3590 cds_ssr_protect(__func__);
3591 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
3592 wdev, data, data_len);
3593 cds_ssr_unprotect(__func__);
3594
3595 return ret;
3596}
3597
3598static const struct
3599nla_policy
3600qca_wlan_vendor_wifi_logger_get_ring_data_policy
3601[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
3602 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
3603 = {.type = NLA_U32 },
3604};
3605
3606/**
3607 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
3608 * @wiphy: WIPHY structure pointer
3609 * @wdev: Wireless device structure pointer
3610 * @data: Pointer to the data received
3611 * @data_len: Length of the data received
3612 *
3613 * This function is used to flush or retrieve the per packet statistics from
3614 * the driver
3615 *
3616 * Return: 0 on success and errno on failure
3617 */
3618static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3619 struct wireless_dev *wdev,
3620 const void *data,
3621 int data_len)
3622{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303623 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003624 uint32_t ring_id;
3625 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3626 struct nlattr *tb
3627 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
3628
Jeff Johnson1f61b612016-02-12 16:28:33 -08003629 ENTER_DEV(wdev->netdev);
3630
Anurag Chouhan6d760662016-02-20 16:05:43 +05303631 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 hdd_err("Command not allowed in FTM mode");
3633 return -EPERM;
3634 }
3635
3636 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303637 if (status)
3638 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639
3640 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
3641 data, data_len,
3642 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
3643 hddLog(LOGE, FL("Invalid attribute"));
3644 return -EINVAL;
3645 }
3646
3647 /* Parse and fetch ring id */
3648 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
3649 hddLog(LOGE, FL("attr ATTR failed"));
3650 return -EINVAL;
3651 }
3652
3653 ring_id = nla_get_u32(
3654 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
3655
3656 if (ring_id == RING_ID_PER_PACKET_STATS) {
3657 wlan_logging_set_per_pkt_stats();
3658 hddLog(LOG1, FL("Flushing/Retrieving packet stats"));
3659 }
3660
3661 hddLog(LOG1, FL("Bug report triggered by framework"));
3662
3663 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
3664 WLAN_LOG_INDICATOR_FRAMEWORK,
Abhishek Singh5ea86532016-04-27 14:10:53 +05303665 WLAN_LOG_REASON_CODE_UNUSED,
3666 true, false);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303667 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003668 hddLog(LOGE, FL("Failed to trigger bug report"));
3669 return -EINVAL;
3670 }
3671
3672 return 0;
3673}
3674
3675/**
3676 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
3677 * @wiphy: WIPHY structure pointer
3678 * @wdev: Wireless device structure pointer
3679 * @data: Pointer to the data received
3680 * @data_len: Length of the data received
3681 *
3682 * This function is used to flush or retrieve the per packet statistics from
3683 * the driver
3684 *
3685 * Return: 0 on success and errno on failure
3686 */
3687static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
3688 struct wireless_dev *wdev,
3689 const void *data,
3690 int data_len)
3691{
3692 int ret = 0;
3693
3694 cds_ssr_protect(__func__);
3695 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
3696 wdev, data, data_len);
3697 cds_ssr_unprotect(__func__);
3698
3699 return ret;
3700}
3701
3702#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
3703/**
3704 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
3705 * @hdd_ctx: HDD context
3706 * @request_id: [input] request id
3707 * @pattern_id: [output] pattern id
3708 *
3709 * This function loops through request id to pattern id array
3710 * if the slot is available, store the request id and return pattern id
3711 * if entry exists, return the pattern id
3712 *
3713 * Return: 0 on success and errno on failure
3714 */
3715static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3716 uint32_t request_id,
3717 uint8_t *pattern_id)
3718{
3719 uint32_t i;
3720
3721 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3722 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3723 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
3724 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
3725 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3726 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3727 return 0;
3728 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
3729 request_id) {
3730 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3731 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3732 return 0;
3733 }
3734 }
3735 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3736 return -EINVAL;
3737}
3738
3739/**
3740 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
3741 * @hdd_ctx: HDD context
3742 * @request_id: [input] request id
3743 * @pattern_id: [output] pattern id
3744 *
3745 * This function loops through request id to pattern id array
3746 * reset request id to 0 (slot available again) and
3747 * return pattern id
3748 *
3749 * Return: 0 on success and errno on failure
3750 */
3751static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
3752 uint32_t request_id,
3753 uint8_t *pattern_id)
3754{
3755 uint32_t i;
3756
3757 mutex_lock(&hdd_ctx->op_ctx.op_lock);
3758 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
3759 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
3760 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
3761 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
3762 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3763 return 0;
3764 }
3765 }
3766 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
3767 return -EINVAL;
3768}
3769
3770
3771/*
3772 * define short names for the global vendor params
3773 * used by __wlan_hdd_cfg80211_offloaded_packets()
3774 */
3775#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
3776#define PARAM_REQUEST_ID \
3777 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
3778#define PARAM_CONTROL \
3779 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
3780#define PARAM_IP_PACKET \
3781 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
3782#define PARAM_SRC_MAC_ADDR \
3783 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
3784#define PARAM_DST_MAC_ADDR \
3785 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
3786#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
3787
3788/**
3789 * wlan_hdd_add_tx_ptrn() - add tx pattern
3790 * @adapter: adapter pointer
3791 * @hdd_ctx: hdd context
3792 * @tb: nl attributes
3793 *
3794 * This function reads the NL attributes and forms a AddTxPtrn message
3795 * posts it to SME.
3796 *
3797 */
3798static int
3799wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3800 struct nlattr **tb)
3801{
3802 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303803 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804 uint32_t request_id, ret, len;
3805 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05303806 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 uint16_t eth_type = htons(ETH_P_IP);
3808
3809 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
3810 hddLog(LOGE, FL("Not in Connected state!"));
3811 return -ENOTSUPP;
3812 }
3813
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303814 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815 if (!add_req) {
3816 hddLog(LOGE, FL("memory allocation failed"));
3817 return -ENOMEM;
3818 }
3819
3820 /* Parse and fetch request Id */
3821 if (!tb[PARAM_REQUEST_ID]) {
3822 hddLog(LOGE, FL("attr request id failed"));
3823 goto fail;
3824 }
3825
3826 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3827 if (request_id == MAX_REQUEST_ID) {
3828 hddLog(LOGE, FL("request_id cannot be MAX"));
3829 return -EINVAL;
3830 }
3831 hddLog(LOG1, FL("Request Id: %u"), request_id);
3832
3833 if (!tb[PARAM_PERIOD]) {
3834 hddLog(LOGE, FL("attr period failed"));
3835 goto fail;
3836 }
3837 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
3838 hddLog(LOG1, FL("Period: %u ms"), add_req->usPtrnIntervalMs);
3839 if (add_req->usPtrnIntervalMs == 0) {
3840 hddLog(LOGE, FL("Invalid interval zero, return failure"));
3841 goto fail;
3842 }
3843
3844 if (!tb[PARAM_SRC_MAC_ADDR]) {
3845 hddLog(LOGE, FL("attr source mac address failed"));
3846 goto fail;
3847 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08003848 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303849 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850 hddLog(LOG1, "input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003851 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852
Anurag Chouhanc5548422016-02-24 18:33:27 +05303853 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08003854 &adapter->macAddressCurrent)) {
3855 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856 goto fail;
3857 }
3858
3859 if (!tb[PARAM_DST_MAC_ADDR]) {
3860 hddLog(LOGE, FL("attr dst mac address failed"));
3861 goto fail;
3862 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303863 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 hddLog(LOG1, "input dst mac address: "MAC_ADDRESS_STR,
3865 MAC_ADDR_ARRAY(dst_addr.bytes));
3866
3867 if (!tb[PARAM_IP_PACKET]) {
3868 hddLog(LOGE, FL("attr ip packet failed"));
3869 goto fail;
3870 }
3871 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
3872 hddLog(LOG1, FL("IP packet len: %u"), add_req->ucPtrnSize);
3873
3874 if (add_req->ucPtrnSize < 0 ||
3875 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
3876 ETH_HLEN)) {
3877 hddLog(LOGE, FL("Invalid IP packet len: %d"),
3878 add_req->ucPtrnSize);
3879 goto fail;
3880 }
3881
3882 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303883 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05303884 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303885 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05303886 QDF_MAC_ADDR_SIZE);
3887 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303888 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 len += 2;
3890
3891 /*
3892 * This is the IP packet, add 14 bytes Ethernet (802.3) header
3893 * ------------------------------------------------------------
3894 * | 14 bytes Ethernet (802.3) header | IP header and payload |
3895 * ------------------------------------------------------------
3896 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303897 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 nla_data(tb[PARAM_IP_PACKET]),
3899 add_req->ucPtrnSize);
3900 add_req->ucPtrnSize += len;
3901
3902 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3903 if (ret) {
3904 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3905 goto fail;
3906 }
3907 add_req->ucPtrnId = pattern_id;
3908 hddLog(LOG1, FL("pattern id: %d"), add_req->ucPtrnId);
3909
3910 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303911 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 hddLog(LOGE,
3913 FL("sme_add_periodic_tx_ptrn failed (err=%d)"), status);
3914 goto fail;
3915 }
3916
3917 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303918 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003919 return 0;
3920
3921fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303922 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003923 return -EINVAL;
3924}
3925
3926/**
3927 * wlan_hdd_del_tx_ptrn() - delete tx pattern
3928 * @adapter: adapter pointer
3929 * @hdd_ctx: hdd context
3930 * @tb: nl attributes
3931 *
3932 * This function reads the NL attributes and forms a DelTxPtrn message
3933 * posts it to SME.
3934 *
3935 */
3936static int
3937wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
3938 struct nlattr **tb)
3939{
3940 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303941 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942 uint32_t request_id, ret;
3943 uint8_t pattern_id = 0;
3944
3945 /* Parse and fetch request Id */
3946 if (!tb[PARAM_REQUEST_ID]) {
3947 hddLog(LOGE, FL("attr request id failed"));
3948 return -EINVAL;
3949 }
3950 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
3951 if (request_id == MAX_REQUEST_ID) {
3952 hddLog(LOGE, FL("request_id cannot be MAX"));
3953 return -EINVAL;
3954 }
3955
3956 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
3957 if (ret) {
3958 hddLog(LOGW, FL("req id to pattern id failed (ret=%d)"), ret);
3959 return -EINVAL;
3960 }
3961
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303962 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 if (!del_req) {
3964 hddLog(LOGE, FL("memory allocation failed"));
3965 return -ENOMEM;
3966 }
3967
Anurag Chouhanc5548422016-02-24 18:33:27 +05303968 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08003969 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970 del_req->ucPtrnId = pattern_id;
3971 hddLog(LOG1, FL("Request Id: %u Pattern id: %d"),
3972 request_id, del_req->ucPtrnId);
3973
3974 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303975 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976 hddLog(LOGE,
3977 FL("sme_del_periodic_tx_ptrn failed (err=%d)"), status);
3978 goto fail;
3979 }
3980
3981 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303982 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003983 return 0;
3984
3985fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303986 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003987 return -EINVAL;
3988}
3989
3990
3991/**
3992 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
3993 * @wiphy: Pointer to wireless phy
3994 * @wdev: Pointer to wireless device
3995 * @data: Pointer to data
3996 * @data_len: Data length
3997 *
3998 * Return: 0 on success, negative errno on failure
3999 */
4000static int
4001__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4002 struct wireless_dev *wdev,
4003 const void *data,
4004 int data_len)
4005{
4006 struct net_device *dev = wdev->netdev;
4007 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4008 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4009 struct nlattr *tb[PARAM_MAX + 1];
4010 uint8_t control;
4011 int ret;
4012 static const struct nla_policy policy[PARAM_MAX + 1] = {
4013 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4014 [PARAM_CONTROL] = { .type = NLA_U32 },
4015 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304016 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304018 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004019 [PARAM_PERIOD] = { .type = NLA_U32 },
4020 };
4021
Jeff Johnson1f61b612016-02-12 16:28:33 -08004022 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023
Anurag Chouhan6d760662016-02-20 16:05:43 +05304024 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 hdd_err("Command not allowed in FTM mode");
4026 return -EPERM;
4027 }
4028
4029 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304030 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004032
4033 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
4034 hddLog(LOGE,
4035 FL("Periodic Tx Pattern Offload feature is not supported in FW!"));
4036 return -ENOTSUPP;
4037 }
4038
4039 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
4040 hddLog(LOGE, FL("Invalid ATTR"));
4041 return -EINVAL;
4042 }
4043
4044 if (!tb[PARAM_CONTROL]) {
4045 hddLog(LOGE, FL("attr control failed"));
4046 return -EINVAL;
4047 }
4048 control = nla_get_u32(tb[PARAM_CONTROL]);
4049 hddLog(LOG1, FL("Control: %d"), control);
4050
4051 if (control == WLAN_START_OFFLOADED_PACKETS)
4052 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4053 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4054 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4055 else {
4056 hddLog(LOGE, FL("Invalid control: %d"), control);
4057 return -EINVAL;
4058 }
4059}
4060
4061/*
4062 * done with short names for the global vendor params
4063 * used by __wlan_hdd_cfg80211_offloaded_packets()
4064 */
4065#undef PARAM_MAX
4066#undef PARAM_REQUEST_ID
4067#undef PARAM_CONTROL
4068#undef PARAM_IP_PACKET
4069#undef PARAM_SRC_MAC_ADDR
4070#undef PARAM_DST_MAC_ADDR
4071#undef PARAM_PERIOD
4072
4073/**
4074 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4075 * @wiphy: wiphy structure pointer
4076 * @wdev: Wireless device structure pointer
4077 * @data: Pointer to the data received
4078 * @data_len: Length of @data
4079 *
4080 * Return: 0 on success; errno on failure
4081 */
4082static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4083 struct wireless_dev *wdev,
4084 const void *data,
4085 int data_len)
4086{
4087 int ret = 0;
4088
4089 cds_ssr_protect(__func__);
4090 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4091 wdev, data, data_len);
4092 cds_ssr_unprotect(__func__);
4093
4094 return ret;
4095}
4096#endif
4097
4098/*
4099 * define short names for the global vendor params
4100 * used by __wlan_hdd_cfg80211_monitor_rssi()
4101 */
4102#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4103#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4104#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4105#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4106#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4107
4108/**
4109 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4110 * @wiphy: Pointer to wireless phy
4111 * @wdev: Pointer to wireless device
4112 * @data: Pointer to data
4113 * @data_len: Data length
4114 *
4115 * Return: 0 on success, negative errno on failure
4116 */
4117static int
4118__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4119 struct wireless_dev *wdev,
4120 const void *data,
4121 int data_len)
4122{
4123 struct net_device *dev = wdev->netdev;
4124 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4125 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4126 struct nlattr *tb[PARAM_MAX + 1];
4127 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304128 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 int ret;
4130 uint32_t control;
4131 static const struct nla_policy policy[PARAM_MAX + 1] = {
4132 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4133 [PARAM_CONTROL] = { .type = NLA_U32 },
4134 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4135 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4136 };
4137
Jeff Johnson1f61b612016-02-12 16:28:33 -08004138 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139
4140 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304141 if (ret)
4142 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143
4144 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
4145 hddLog(LOGE, FL("Not in Connected state!"));
4146 return -ENOTSUPP;
4147 }
4148
4149 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
4150 hddLog(LOGE, FL("Invalid ATTR"));
4151 return -EINVAL;
4152 }
4153
4154 if (!tb[PARAM_REQUEST_ID]) {
4155 hddLog(LOGE, FL("attr request id failed"));
4156 return -EINVAL;
4157 }
4158
4159 if (!tb[PARAM_CONTROL]) {
4160 hddLog(LOGE, FL("attr control failed"));
4161 return -EINVAL;
4162 }
4163
4164 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4165 req.session_id = adapter->sessionId;
4166 control = nla_get_u32(tb[PARAM_CONTROL]);
4167
4168 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4169 req.control = true;
4170 if (!tb[PARAM_MIN_RSSI]) {
4171 hddLog(LOGE, FL("attr min rssi failed"));
4172 return -EINVAL;
4173 }
4174
4175 if (!tb[PARAM_MAX_RSSI]) {
4176 hddLog(LOGE, FL("attr max rssi failed"));
4177 return -EINVAL;
4178 }
4179
4180 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4181 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4182
4183 if (!(req.min_rssi < req.max_rssi)) {
4184 hddLog(LOGW, FL("min_rssi: %d must be less than max_rssi: %d"),
4185 req.min_rssi, req.max_rssi);
4186 return -EINVAL;
4187 }
4188 hddLog(LOG1, FL("Min_rssi: %d Max_rssi: %d"),
4189 req.min_rssi, req.max_rssi);
4190
4191 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4192 req.control = false;
4193 else {
4194 hddLog(LOGE, FL("Invalid control cmd: %d"), control);
4195 return -EINVAL;
4196 }
4197 hddLog(LOG1, FL("Request Id: %u Session_id: %d Control: %d"),
4198 req.request_id, req.session_id, req.control);
4199
4200 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304201 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 hddLog(LOGE,
4203 FL("sme_set_rssi_monitoring failed(err=%d)"), status);
4204 return -EINVAL;
4205 }
4206
4207 return 0;
4208}
4209
4210/*
4211 * done with short names for the global vendor params
4212 * used by __wlan_hdd_cfg80211_monitor_rssi()
4213 */
4214#undef PARAM_MAX
4215#undef PARAM_CONTROL
4216#undef PARAM_REQUEST_ID
4217#undef PARAM_MAX_RSSI
4218#undef PARAM_MIN_RSSI
4219
4220/**
4221 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4222 * @wiphy: wiphy structure pointer
4223 * @wdev: Wireless device structure pointer
4224 * @data: Pointer to the data received
4225 * @data_len: Length of @data
4226 *
4227 * Return: 0 on success; errno on failure
4228 */
4229static int
4230wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4231 const void *data, int data_len)
4232{
4233 int ret;
4234
4235 cds_ssr_protect(__func__);
4236 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4237 cds_ssr_unprotect(__func__);
4238
4239 return ret;
4240}
4241
4242/**
4243 * hdd_rssi_threshold_breached() - rssi breached NL event
4244 * @hddctx: HDD context
4245 * @data: rssi breached event data
4246 *
4247 * This function reads the rssi breached event %data and fill in the skb with
4248 * NL attributes and send up the NL event.
4249 *
4250 * Return: none
4251 */
4252void hdd_rssi_threshold_breached(void *hddctx,
4253 struct rssi_breach_event *data)
4254{
4255 hdd_context_t *hdd_ctx = hddctx;
4256 struct sk_buff *skb;
4257
4258 ENTER();
4259
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304260 if (wlan_hdd_validate_context(hdd_ctx))
4261 return;
4262 if (!data) {
4263 hddLog(LOGE, FL("data is null"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 return;
4265 }
4266
4267 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4268 NULL,
4269 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4270 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4271 GFP_KERNEL);
4272
4273 if (!skb) {
4274 hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
4275 return;
4276 }
4277
4278 hddLog(LOG1, "Req Id: %u Current rssi: %d",
4279 data->request_id, data->curr_rssi);
4280 hddLog(LOG1, "Current BSSID: "MAC_ADDRESS_STR,
4281 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4282
4283 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4284 data->request_id) ||
4285 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4286 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4287 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4288 data->curr_rssi)) {
4289 hddLog(LOGE, FL("nla put fail"));
4290 goto fail;
4291 }
4292
4293 cfg80211_vendor_event(skb, GFP_KERNEL);
4294 return;
4295
4296fail:
4297 kfree_skb(skb);
4298 return;
4299}
4300
4301/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
4302 * @wiphy: Pointer to wireless phy
4303 * @wdev: Pointer to wireless device
4304 * @data: Pointer to data
4305 * @data_len: Data length
4306 *
4307 * This function return the preferred frequency list generated by the policy
4308 * manager.
4309 *
4310 * Return: success or failure code
4311 */
4312static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4313 struct wireless_dev
4314 *wdev, const void *data,
4315 int data_len)
4316{
4317 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4318 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304319 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05304320 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004321 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05304322 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323 enum cds_con_mode intf_mode;
4324 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4325 struct sk_buff *reply_skb;
4326
Jeff Johnson1f61b612016-02-12 16:28:33 -08004327 ENTER_DEV(wdev->netdev);
4328
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 ret = wlan_hdd_validate_context(hdd_ctx);
4330 if (ret)
4331 return -EINVAL;
4332
4333 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4334 data, data_len, NULL)) {
4335 hdd_err("Invalid ATTR");
4336 return -EINVAL;
4337 }
4338
4339 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4340 hdd_err("attr interface type failed");
4341 return -EINVAL;
4342 }
4343
4344 intf_mode = nla_get_u32(tb
4345 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4346
4347 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4348 hdd_err("Invalid interface type");
4349 return -EINVAL;
4350 }
4351
4352 hdd_debug("Userspace requested pref freq list");
4353
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05304354 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
4355 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304356 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 hdd_err("Get pcl failed");
4358 return -EINVAL;
4359 }
4360
4361 /* convert channel number to frequency */
4362 for (i = 0; i < pcl_len; i++) {
4363 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4364 freq_list[i] =
4365 ieee80211_channel_to_frequency(pcl[i],
4366 IEEE80211_BAND_2GHZ);
4367 else
4368 freq_list[i] =
4369 ieee80211_channel_to_frequency(pcl[i],
4370 IEEE80211_BAND_5GHZ);
4371 }
4372
4373 /* send the freq_list back to supplicant */
4374 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4375 sizeof(u32) *
4376 pcl_len +
4377 NLMSG_HDRLEN);
4378
4379 if (!reply_skb) {
4380 hdd_err("Allocate reply_skb failed");
4381 return -EINVAL;
4382 }
4383
4384 if (nla_put_u32(reply_skb,
4385 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4386 intf_mode) ||
4387 nla_put(reply_skb,
4388 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4389 sizeof(uint32_t) * pcl_len,
4390 freq_list)) {
4391 hdd_err("nla put fail");
4392 kfree_skb(reply_skb);
4393 return -EINVAL;
4394 }
4395
4396 return cfg80211_vendor_cmd_reply(reply_skb);
4397}
4398
4399/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4400 * @wiphy: Pointer to wireless phy
4401 * @wdev: Pointer to wireless device
4402 * @data: Pointer to data
4403 * @data_len: Data length
4404 *
4405 * This function return the preferred frequency list generated by the policy
4406 * manager.
4407 *
4408 * Return: success or failure code
4409 */
4410static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4411 struct wireless_dev
4412 *wdev, const void *data,
4413 int data_len)
4414{
4415 int ret = 0;
4416
4417 cds_ssr_protect(__func__);
4418 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
4419 data, data_len);
4420 cds_ssr_unprotect(__func__);
4421
4422 return ret;
4423}
4424
4425/**
4426 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4427 * @wiphy: Pointer to wireless phy
4428 * @wdev: Pointer to wireless device
4429 * @data: Pointer to data
4430 * @data_len: Data length
4431 *
4432 * Return: 0 on success, negative errno on failure
4433 */
4434static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4435 struct wireless_dev *wdev,
4436 const void *data,
4437 int data_len)
4438{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304439 struct net_device *ndev = wdev->netdev;
4440 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004441 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4442 int ret = 0;
4443 enum cds_con_mode intf_mode;
4444 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4445 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004446
Jeff Johnson1f61b612016-02-12 16:28:33 -08004447 ENTER_DEV(ndev);
4448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004449 ret = wlan_hdd_validate_context(hdd_ctx);
4450 if (ret)
4451 return ret;
4452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004453 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
4454 data, data_len, NULL)) {
4455 hdd_err("Invalid ATTR");
4456 return -EINVAL;
4457 }
4458
4459 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
4460 hdd_err("attr interface type failed");
4461 return -EINVAL;
4462 }
4463
4464 intf_mode = nla_get_u32(tb
4465 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
4466
4467 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4468 hdd_err("Invalid interface type");
4469 return -EINVAL;
4470 }
4471
4472 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
4473 hdd_err("attr probable freq failed");
4474 return -EINVAL;
4475 }
4476
4477 channel_hint = cds_freq_to_chan(nla_get_u32(tb
4478 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
4479
4480 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08004481 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 channel_hint, HW_MODE_20_MHZ)) {
4483 hdd_err("Set channel hint failed due to concurrency check");
4484 return -EINVAL;
4485 }
4486
Krunal Soni09e55032016-06-07 10:06:55 -07004487 if (0 != wlan_hdd_check_remain_on_channel(adapter))
4488 hdd_warn("Remain On Channel Pending");
4489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 if (hdd_ctx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304491 ret = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304492 if (!QDF_IS_STATUS_SUCCESS(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 hdd_err("clearing event failed");
4494
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05304495 ret = cds_current_connections_update(adapter->sessionId,
4496 channel_hint,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +05304497 SIR_UPDATE_REASON_SET_OPER_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304498 if (QDF_STATUS_E_FAILURE == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 /* return in the failure case */
4500 hdd_err("ERROR: connections update failed!!");
4501 return -EINVAL;
4502 }
4503
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304504 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 /*
4506 * Success is the only case for which we expect hw mode
4507 * change to take place, hence we need to wait.
4508 * For any other return value it should be a pass
4509 * through
4510 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304511 ret = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304512 if (!QDF_IS_STATUS_SUCCESS(ret)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05304513 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514 return -EINVAL;
4515 }
4516
4517 }
4518 }
4519
4520 return 0;
4521}
4522
4523/**
4524 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
4525 * @wiphy: Pointer to wireless phy
4526 * @wdev: Pointer to wireless device
4527 * @data: Pointer to data
4528 * @data_len: Data length
4529 *
4530 * Return: 0 on success, negative errno on failure
4531 */
4532static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
4533 struct wireless_dev *wdev,
4534 const void *data,
4535 int data_len)
4536{
4537 int ret = 0;
4538
4539 cds_ssr_protect(__func__);
4540 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
4541 data, data_len);
4542 cds_ssr_unprotect(__func__);
4543
4544 return ret;
4545}
4546
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304547static const struct
4548nla_policy
4549qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
4550 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
4551};
4552
4553/**
4554 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
4555 * @wiphy: WIPHY structure pointer
4556 * @wdev: Wireless device structure pointer
4557 * @data: Pointer to the data received
4558 * @data_len: Length of the data received
4559 *
4560 * This function is used to get link properties like nss, rate flags and
4561 * operating frequency for the active connection with the given peer.
4562 *
4563 * Return: 0 on success and errno on failure
4564 */
4565static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4566 struct wireless_dev *wdev,
4567 const void *data,
4568 int data_len)
4569{
4570 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4571 struct net_device *dev = wdev->netdev;
4572 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4573 hdd_station_ctx_t *hdd_sta_ctx;
4574 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05304575 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304576 uint32_t sta_id;
4577 struct sk_buff *reply_skb;
4578 uint32_t rate_flags = 0;
4579 uint8_t nss;
4580 uint8_t final_rate_flags = 0;
4581 uint32_t freq;
4582
Jeff Johnson1f61b612016-02-12 16:28:33 -08004583 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304584
Anurag Chouhan6d760662016-02-20 16:05:43 +05304585 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304586 hdd_err("Command not allowed in FTM mode");
4587 return -EPERM;
4588 }
4589
4590 if (0 != wlan_hdd_validate_context(hdd_ctx))
4591 return -EINVAL;
4592
4593 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
4594 qca_wlan_vendor_attr_policy)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304595 hddLog(QDF_TRACE_LEVEL_ERROR, FL("Invalid attribute"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304596 return -EINVAL;
4597 }
4598
4599 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304600 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304601 FL("Attribute peerMac not provided for mode=%d"),
4602 adapter->device_mode);
4603 return -EINVAL;
4604 }
4605
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304606 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05304607 QDF_MAC_ADDR_SIZE);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304608 hddLog(QDF_TRACE_LEVEL_INFO,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304609 FL("peerMac="MAC_ADDRESS_STR" for device_mode:%d"),
4610 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
4611
Krunal Sonib4326f22016-03-10 13:05:51 -08004612 if (adapter->device_mode == QDF_STA_MODE ||
4613 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304614 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4615 if ((hdd_sta_ctx->conn_info.connState !=
4616 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304617 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304618 peer_mac, QDF_MAC_ADDR_SIZE)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304619 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304620 FL("Not Associated to mac "MAC_ADDRESS_STR),
4621 MAC_ADDR_ARRAY(peer_mac));
4622 return -EINVAL;
4623 }
4624
4625 nss = hdd_sta_ctx->conn_info.nss;
4626 freq = cds_chan_to_freq(
4627 hdd_sta_ctx->conn_info.operationChannel);
4628 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08004629 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
4630 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304631
4632 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
4633 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05304634 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304635 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304636 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304637 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304638 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304639 break;
4640 }
4641
4642 if (WLAN_MAX_STA_COUNT == sta_id) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304643 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304644 FL("No active peer with mac="MAC_ADDRESS_STR),
4645 MAC_ADDR_ARRAY(peer_mac));
4646 return -EINVAL;
4647 }
4648
4649 nss = adapter->aStaInfo[sta_id].nss;
4650 freq = cds_chan_to_freq(
4651 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
4652 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
4653 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304654 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304655 FL("Not Associated! with mac "MAC_ADDRESS_STR),
4656 MAC_ADDR_ARRAY(peer_mac));
4657 return -EINVAL;
4658 }
4659
4660 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
4661 if (rate_flags & eHAL_TX_RATE_VHT80) {
4662 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004663#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304664 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004665#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304666 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
4667 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004668#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304669 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004670#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304671 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
4672 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
4673 } else if (rate_flags &
4674 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
4675 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004676#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304677 if (rate_flags & eHAL_TX_RATE_HT40)
4678 final_rate_flags |=
4679 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08004680#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304681 }
4682
4683 if (rate_flags & eHAL_TX_RATE_SGI) {
4684 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
4685 final_rate_flags |= RATE_INFO_FLAGS_MCS;
4686 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
4687 }
4688 }
4689
4690 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4691 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
4692
4693 if (NULL == reply_skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304694 hddLog(QDF_TRACE_LEVEL_ERROR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304695 FL("getLinkProperties: skb alloc failed"));
4696 return -EINVAL;
4697 }
4698
4699 if (nla_put_u8(reply_skb,
4700 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
4701 nss) ||
4702 nla_put_u8(reply_skb,
4703 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
4704 final_rate_flags) ||
4705 nla_put_u32(reply_skb,
4706 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
4707 freq)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304708 hddLog(QDF_TRACE_LEVEL_ERROR, FL("nla_put failed"));
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05304709 kfree_skb(reply_skb);
4710 return -EINVAL;
4711 }
4712
4713 return cfg80211_vendor_cmd_reply(reply_skb);
4714}
4715
4716/**
4717 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
4718 * properties.
4719 * @wiphy: WIPHY structure pointer
4720 * @wdev: Wireless device structure pointer
4721 * @data: Pointer to the data received
4722 * @data_len: Length of the data received
4723 *
4724 * This function is used to get link properties like nss, rate flags and
4725 * operating frequency for the active connection with the given peer.
4726 *
4727 * Return: 0 on success and errno on failure
4728 */
4729static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
4730 struct wireless_dev *wdev,
4731 const void *data,
4732 int data_len)
4733{
4734 int ret = 0;
4735
4736 cds_ssr_protect(__func__);
4737 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
4738 wdev, data, data_len);
4739 cds_ssr_unprotect(__func__);
4740
4741 return ret;
4742}
4743
Peng Xu278d0122015-09-24 16:34:17 -07004744static const struct
4745nla_policy
4746qca_wlan_vendor_ota_test_policy
4747[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
4748 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
4749};
4750
4751/**
4752 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
4753 * @wiphy: Pointer to wireless phy
4754 * @wdev: Pointer to wireless device
4755 * @data: Pointer to data
4756 * @data_len: Data length
4757 *
4758 * Return: 0 on success, negative errno on failure
4759 */
4760static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4761 struct wireless_dev *wdev,
4762 const void *data,
4763 int data_len)
4764{
4765 struct net_device *dev = wdev->netdev;
4766 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4767 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
4768 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4769 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
4770 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304771 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07004772 uint32_t current_roam_state;
4773
Jeff Johnson1f61b612016-02-12 16:28:33 -08004774 ENTER_DEV(dev);
4775
Anurag Chouhan6d760662016-02-20 16:05:43 +05304776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07004777 hdd_err("Command not allowed in FTM mode");
4778 return -EPERM;
4779 }
4780
4781 if (0 != wlan_hdd_validate_context(hdd_ctx))
4782 return -EINVAL;
4783
4784 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
4785 data, data_len,
4786 qca_wlan_vendor_ota_test_policy)) {
4787 hdd_err("invalid attr");
4788 return -EINVAL;
4789 }
4790
4791 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
4792 hdd_err("attr ota test failed");
4793 return -EINVAL;
4794 }
4795
4796 ota_enable = nla_get_u8(
4797 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
4798
4799 hdd_info(" OTA test enable = %d", ota_enable);
4800 if (ota_enable != 1) {
4801 hdd_err("Invalid value, only enable test mode is supported!");
4802 return -EINVAL;
4803 }
4804
4805 current_roam_state =
4806 sme_get_current_roam_state(hal, adapter->sessionId);
4807 status = sme_stop_roaming(hal, adapter->sessionId,
4808 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304809 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004810 hdd_err("Enable/Disable roaming failed");
4811 return -EINVAL;
4812 }
4813
4814 status = sme_ps_enable_disable(hal, adapter->sessionId,
4815 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304816 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07004817 hdd_err("Enable/Disable power save failed");
4818 /* restore previous roaming setting */
4819 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
4820 current_roam_state == eCSR_ROAMING_STATE_JOINED)
4821 status = sme_start_roaming(hal, adapter->sessionId,
4822 eCsrHddIssued);
4823 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
4824 current_roam_state == eCSR_ROAMING_STATE_IDLE)
4825 status = sme_stop_roaming(hal, adapter->sessionId,
4826 eCsrHddIssued);
4827
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304828 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07004829 hdd_err("Restoring roaming state failed");
4830
4831 return -EINVAL;
4832 }
4833
4834
4835 return 0;
4836}
4837
4838/**
4839 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
4840 * @wiphy: Pointer to wireless phy
4841 * @wdev: Pointer to wireless device
4842 * @data: Pointer to data
4843 * @data_len: Data length
4844 *
4845 * Return: 0 on success, negative errno on failure
4846 */
4847static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
4848 struct wireless_dev *wdev,
4849 const void *data,
4850 int data_len)
4851{
4852 int ret = 0;
4853
4854 cds_ssr_protect(__func__);
4855 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
4856 cds_ssr_unprotect(__func__);
4857
4858 return ret;
4859}
4860
Peng Xu4d67c8f2015-10-16 16:02:26 -07004861/**
4862 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4863 * @wiphy: Pointer to wireless phy
4864 * @wdev: Pointer to wireless device
4865 * @data: Pointer to data
4866 * @data_len: Data length
4867 *
4868 * Return: 0 on success, negative errno on failure
4869 */
4870static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4871 struct wireless_dev *wdev,
4872 const void *data,
4873 int data_len)
4874{
4875 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4876 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07004877 hdd_adapter_t *adapter;
4878 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07004879 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
4880 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07004881 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07004882
Jeff Johnson1f61b612016-02-12 16:28:33 -08004883 ENTER_DEV(dev);
4884
Peng Xu4d67c8f2015-10-16 16:02:26 -07004885 ret = wlan_hdd_validate_context(hdd_ctx);
4886 if (ret)
4887 return ret;
4888
4889 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4890
4891 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
4892 data, data_len, NULL)) {
4893 hdd_err("Invalid ATTR");
4894 return -EINVAL;
4895 }
4896
4897 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
4898 hdd_err("attr tx power scale failed");
4899 return -EINVAL;
4900 }
4901
4902 scale_value = nla_get_u8(tb
4903 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
4904
4905 if (scale_value > MAX_TXPOWER_SCALE) {
4906 hdd_err("Invalid tx power scale level");
4907 return -EINVAL;
4908 }
4909
Peng Xu62c8c432016-05-09 15:23:02 -07004910 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07004911
Peng Xu62c8c432016-05-09 15:23:02 -07004912 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07004913 hdd_err("Set tx power scale failed");
4914 return -EINVAL;
4915 }
4916
4917 return 0;
4918}
4919
4920/**
4921 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
4922 * @wiphy: Pointer to wireless phy
4923 * @wdev: Pointer to wireless device
4924 * @data: Pointer to data
4925 * @data_len: Data length
4926 *
4927 * Return: 0 on success, negative errno on failure
4928 */
4929static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
4930 struct wireless_dev *wdev,
4931 const void *data,
4932 int data_len)
4933{
Peng Xu62c8c432016-05-09 15:23:02 -07004934 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07004935
4936 cds_ssr_protect(__func__);
4937 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
4938 data, data_len);
4939 cds_ssr_unprotect(__func__);
4940
4941 return ret;
4942}
4943
4944/**
4945 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
4946 * @wiphy: Pointer to wireless phy
4947 * @wdev: Pointer to wireless device
4948 * @data: Pointer to data
4949 * @data_len: Data length
4950 *
4951 * Return: 0 on success, negative errno on failure
4952 */
4953static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
4954 struct wireless_dev *wdev,
4955 const void *data,
4956 int data_len)
4957{
4958 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4959 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07004960 hdd_adapter_t *adapter;
4961 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07004962 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
4963 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07004964 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07004965
Jeff Johnson1f61b612016-02-12 16:28:33 -08004966 ENTER_DEV(dev);
4967
Peng Xu4d67c8f2015-10-16 16:02:26 -07004968 ret = wlan_hdd_validate_context(hdd_ctx);
4969 if (ret)
4970 return ret;
4971
4972 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4973
4974 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
4975 data, data_len, NULL)) {
4976 hdd_err("Invalid ATTR");
4977 return -EINVAL;
4978 }
4979
4980 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
4981 hdd_err("attr tx power decrease db value failed");
4982 return -EINVAL;
4983 }
4984
4985 scale_value = nla_get_u8(tb
4986 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
4987
Peng Xu62c8c432016-05-09 15:23:02 -07004988 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
4989 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07004990
Peng Xu62c8c432016-05-09 15:23:02 -07004991 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07004992 hdd_err("Set tx power decrease db failed");
4993 return -EINVAL;
4994 }
4995
4996 return 0;
4997}
4998
4999/**
5000 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5001 * @wiphy: Pointer to wireless phy
5002 * @wdev: Pointer to wireless device
5003 * @data: Pointer to data
5004 * @data_len: Data length
5005 *
5006 * Return: 0 on success, negative errno on failure
5007 */
5008static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5009 struct wireless_dev *wdev,
5010 const void *data,
5011 int data_len)
5012{
Peng Xu62c8c432016-05-09 15:23:02 -07005013 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005014
5015 cds_ssr_protect(__func__);
5016 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5017 data, data_len);
5018 cds_ssr_unprotect(__func__);
5019
5020 return ret;
5021}
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305022/*
5023 * define short names for the global vendor params
5024 * used by __wlan_hdd_cfg80211_bpf_offload()
5025 */
5026#define BPF_INVALID \
5027 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
5028#define BPF_SET_RESET \
5029 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
5030#define BPF_VERSION \
5031 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
5032#define BPF_FILTER_ID \
5033 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
5034#define BPF_PACKET_SIZE \
5035 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
5036#define BPF_CURRENT_OFFSET \
5037 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
5038#define BPF_PROGRAM \
5039 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
5040#define BPF_MAX \
5041 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07005042
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305043static const struct nla_policy
5044wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
5045 [BPF_SET_RESET] = {.type = NLA_U32},
5046 [BPF_VERSION] = {.type = NLA_U32},
5047 [BPF_FILTER_ID] = {.type = NLA_U32},
5048 [BPF_PACKET_SIZE] = {.type = NLA_U32},
5049 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
5050 [BPF_PROGRAM] = {.type = NLA_U8},
5051};
5052
5053/**
5054 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
5055 * @hdd_context: hdd_context
5056 * @bpf_get_offload: struct for get offload
5057 *
5058 * This function receives the response/data from the lower layer and
5059 * checks to see if the thread is still waiting then post the results to
5060 * upper layer, if the request has timed out then ignore.
5061 *
5062 * Return: None
5063 */
5064void hdd_get_bpf_offload_cb(void *hdd_context,
5065 struct sir_bpf_get_offload *data)
5066{
5067 hdd_context_t *hdd_ctx = hdd_context;
5068 struct hdd_bpf_context *context;
5069
5070 ENTER();
5071
5072 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
5073 hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"),
5074 data);
5075 return;
5076 }
5077
5078 spin_lock(&hdd_context_lock);
5079
5080 context = &bpf_context;
5081 /* The caller presumably timed out so there is nothing we can do */
5082 if (context->magic != BPF_CONTEXT_MAGIC) {
5083 spin_unlock(&hdd_context_lock);
5084 return;
5085 }
5086
5087 /* context is valid so caller is still waiting */
5088 /* paranoia: invalidate the magic */
5089 context->magic = 0;
5090
5091 context->capability_response = *data;
5092 complete(&context->completion);
5093
5094 spin_unlock(&hdd_context_lock);
5095
5096 return;
5097}
5098
5099/**
5100 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
5101 * @hdd_context: hdd_context
5102 * @bpf_get_offload: struct for get offload
5103 *
5104 * Return: 0 on success, error number otherwise.
5105 */
5106static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
5107 struct sir_bpf_get_offload *bpf_get_offload)
5108{
5109 struct sk_buff *skb;
5110 uint32_t nl_buf_len;
5111
5112 ENTER();
5113
5114 nl_buf_len = NLMSG_HDRLEN;
5115 nl_buf_len +=
5116 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
5117 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
5118
5119 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
5120 if (!skb) {
5121 hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
5122 return -ENOMEM;
5123 }
5124
5125 hddLog(LOG1, "BPF Version: %u BPF max bytes: %u",
5126 bpf_get_offload->bpf_version,
5127 bpf_get_offload->max_bytes_for_bpf_inst);
5128
5129 if (nla_put_u32(skb, BPF_PACKET_SIZE,
5130 bpf_get_offload->max_bytes_for_bpf_inst) ||
5131 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
5132 hddLog(LOGE, FL("nla put failure"));
5133 goto nla_put_failure;
5134 }
5135
5136 cfg80211_vendor_cmd_reply(skb);
5137 EXIT();
5138 return 0;
5139
5140nla_put_failure:
5141 kfree_skb(skb);
5142 return -EINVAL;
5143}
5144
5145/**
5146 * hdd_get_bpf_offload - Get BPF offload Capabilities
5147 * @hdd_ctx: Hdd context
5148 *
5149 * Return: 0 on success, errno on failure
5150 */
5151static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
5152{
5153 unsigned long rc;
5154 struct hdd_bpf_context *context;
5155 QDF_STATUS status;
5156 int ret;
5157
5158 ENTER();
5159
5160 spin_lock(&hdd_context_lock);
5161 context = &bpf_context;
5162 context->magic = BPF_CONTEXT_MAGIC;
5163 INIT_COMPLETION(context->completion);
5164 spin_unlock(&hdd_context_lock);
5165
5166 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
5167 if (!QDF_IS_STATUS_SUCCESS(status)) {
5168 hddLog(LOGE, FL("Unable to retrieve BPF caps"));
5169 return -EINVAL;
5170 }
5171 /* request was sent -- wait for the response */
5172 rc = wait_for_completion_timeout(&context->completion,
5173 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
5174 if (!rc) {
5175 hddLog(LOGE, FL("Target response timed out"));
5176 spin_lock(&hdd_context_lock);
5177 context->magic = 0;
5178 spin_unlock(&hdd_context_lock);
5179
5180 return -ETIMEDOUT;
5181 }
5182 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
5183 &bpf_context.capability_response);
5184 if (ret)
5185 hddLog(LOGE, FL("Failed to post get bpf capabilities"));
5186
5187 EXIT();
5188 return ret;
5189}
5190
5191/**
5192 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
5193 * @hdd_ctx: Hdd context
5194 * @tb: Length of @data
5195 * @session_id: Session identifier
5196 *
5197 * Return: 0 on success; errno on failure
5198 */
5199static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
5200 struct nlattr **tb,
5201 uint8_t session_id)
5202{
5203 struct sir_bpf_set_offload *bpf_set_offload;
5204 QDF_STATUS status;
5205 int prog_len;
5206
5207 ENTER();
5208
5209 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
5210 if (bpf_set_offload == NULL) {
5211 hddLog(LOGE, FL("qdf_mem_malloc failed for bpf_set_offload"));
5212 return -ENOMEM;
5213 }
5214 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
5215
5216 /* Parse and fetch bpf packet size */
5217 if (!tb[BPF_PACKET_SIZE]) {
5218 hddLog(LOGE, FL("attr bpf packet size failed"));
5219 goto fail;
5220 }
5221 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
5222
5223 if (!bpf_set_offload->total_length) {
5224 hddLog(LOG1, FL("BPF reset packet filter received"));
5225 goto post_sme;
5226 }
5227
5228 /* Parse and fetch bpf program */
5229 if (!tb[BPF_PROGRAM]) {
5230 hddLog(LOGE, FL("attr bpf program failed"));
5231 goto fail;
5232 }
5233
5234 prog_len = nla_len(tb[BPF_PROGRAM]);
5235 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
5236 bpf_set_offload->current_length = prog_len;
5237 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
5238 bpf_set_offload->session_id = session_id;
5239
5240 /* Parse and fetch filter Id */
5241 if (!tb[BPF_FILTER_ID]) {
5242 hddLog(LOGE, FL("attr filter id failed"));
5243 goto fail;
5244 }
5245 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
5246
5247 /* Parse and fetch current offset */
5248 if (!tb[BPF_CURRENT_OFFSET]) {
5249 hddLog(LOGE, FL("attr current offset failed"));
5250 goto fail;
5251 }
5252 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
5253
5254post_sme:
5255 hddLog(LOG1, FL("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d"),
5256 bpf_set_offload->session_id,
5257 bpf_set_offload->version,
5258 bpf_set_offload->filter_id,
5259 bpf_set_offload->total_length,
5260 bpf_set_offload->current_length,
5261 bpf_set_offload->current_offset);
5262
5263 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
5264 if (!QDF_IS_STATUS_SUCCESS(status)) {
5265 hddLog(LOGE,
5266 FL("sme_set_bpf_instructions failed(err=%d)"), status);
5267 goto fail;
5268 }
5269 EXIT();
5270 if (bpf_set_offload->current_length)
5271 qdf_mem_free(bpf_set_offload->program);
5272 qdf_mem_free(bpf_set_offload);
5273 return 0;
5274
5275fail:
5276 if (bpf_set_offload->current_length)
5277 qdf_mem_free(bpf_set_offload->program);
5278 qdf_mem_free(bpf_set_offload);
5279 return -EINVAL;
5280}
5281
5282/**
5283 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
5284 * @wiphy: wiphy structure pointer
5285 * @wdev: Wireless device structure pointer
5286 * @data: Pointer to the data received
5287 * @data_len: Length of @data
5288 *
5289 * Return: 0 on success; errno on failure
5290 */
5291static int
5292__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
5293 struct wireless_dev *wdev,
5294 const void *data, int data_len)
5295{
5296 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5297 struct net_device *dev = wdev->netdev;
5298 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5299 struct nlattr *tb[BPF_MAX + 1];
5300 int ret_val, packet_filter_subcmd;
5301
5302 ENTER();
5303
5304 ret_val = wlan_hdd_validate_context(hdd_ctx);
5305 if (ret_val)
5306 return ret_val;
5307
5308 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5309 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5310 return -EINVAL;
5311 }
5312
5313 if (!hdd_ctx->bpf_enabled) {
5314 hddLog(LOGE, FL("BPF offload is not supported by firmware"));
5315 return -ENOTSUPP;
5316 }
5317
5318 if (nla_parse(tb, BPF_MAX, data, data_len,
5319 wlan_hdd_bpf_offload_policy)) {
5320 hddLog(LOGE, FL("Invalid ATTR"));
5321 return -EINVAL;
5322 }
5323
5324 if (!tb[BPF_SET_RESET]) {
5325 hddLog(LOGE, FL("attr bpf set reset failed"));
5326 return -EINVAL;
5327 }
5328
5329 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
5330
5331 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
5332 return hdd_get_bpf_offload(hdd_ctx);
5333 else
5334 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
5335 pAdapter->sessionId);
5336}
5337
5338/**
5339 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
5340 * @wiphy: wiphy structure pointer
5341 * @wdev: Wireless device structure pointer
5342 * @data: Pointer to the data received
5343 * @data_len: Length of @data
5344 *
5345 * Return: 0 on success; errno on failure
5346 */
5347
5348static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
5349 struct wireless_dev *wdev,
5350 const void *data, int data_len)
5351{
5352 int ret;
5353
5354 cds_ssr_protect(__func__);
5355 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
5356 cds_ssr_unprotect(__func__);
5357
5358 return ret;
5359}
5360
5361/**
5362 * hdd_init_bpf_completion() - Initialize the completion event for bpf
5363 *
5364 * Return: None
5365 */
5366void hdd_init_bpf_completion(void)
5367{
5368 init_completion(&bpf_context.completion);
5369}
5370
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05305371static const struct nla_policy
5372wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
5373 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
5374};
5375
5376/**
5377 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
5378 * SAP is on unsafe channel.
5379 * @wiphy: wiphy structure pointer
5380 * @wdev: Wireless device structure pointer
5381 * @data: Pointer to the data received
5382 * @data_len: Length of @data
5383 *
5384 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
5385 * driver.
5386 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
5387 * will initiate restart of sap.
5388 *
5389 * Return: 0 on success; errno on failure
5390 */
5391static int
5392__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
5393 struct wireless_dev *wdev,
5394 const void *data, int data_len)
5395{
5396 struct net_device *ndev = wdev->netdev;
5397 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
5398 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5399 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
5400 uint8_t config_channel = 0;
5401 hdd_ap_ctx_t *ap_ctx;
5402 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305403 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05305404
5405 ENTER();
5406
5407 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5408 hddLog(LOGE, FL("Command not allowed in FTM mode"));
5409 return -EINVAL;
5410 }
5411
5412 ret = wlan_hdd_validate_context(hdd_ctx);
5413 if (0 != ret)
5414 return -EINVAL;
5415
5416 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
5417 data, data_len,
5418 wlan_hdd_sap_config_policy)) {
5419 hddLog(LOGE, FL("invalid attr"));
5420 return -EINVAL;
5421 }
5422
5423 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
5424 if (!test_bit(SOFTAP_BSS_STARTED,
5425 &hostapd_adapter->event_flags)) {
5426 hdd_err("SAP is not started yet. Restart sap will be invalid");
5427 return -EINVAL;
5428 }
5429
5430 config_channel =
5431 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
5432
5433 if (!((IS_24G_CH(config_channel)) ||
5434 (IS_5G_CH(config_channel)))) {
5435 hdd_err("Channel %d is not valid to restart SAP",
5436 config_channel);
5437 return -ENOTSUPP;
5438 }
5439
5440 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
5441 ap_ctx->sapConfig.channel = config_channel;
5442 ap_ctx->sapConfig.ch_params.ch_width =
5443 ap_ctx->sapConfig.ch_width_orig;
5444
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07005445 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05305446 ap_ctx->sapConfig.sec_ch,
5447 &ap_ctx->sapConfig.ch_params);
5448
5449 cds_restart_sap(hostapd_adapter);
5450 }
5451
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305452 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
5453 uint32_t freq_len, i;
5454 uint32_t *freq;
5455 uint8_t chans[QDF_MAX_NUM_CHAN];
5456
5457 hdd_debug("setting mandatory freq/chan list");
5458
5459 freq_len = nla_len(
5460 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
5461 sizeof(uint32_t);
5462
5463 if (freq_len > QDF_MAX_NUM_CHAN) {
5464 hdd_err("insufficient space to hold channels");
5465 return -ENOMEM;
5466 }
5467
5468 freq = nla_data(
5469 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
5470
5471 hdd_debug("freq_len=%d", freq_len);
5472
5473 for (i = 0; i < freq_len; i++) {
5474 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5475 hdd_debug("freq[%d]=%d", i, freq[i]);
5476 }
5477
5478 status = cds_set_sap_mandatory_channels(chans, freq_len);
5479 if (QDF_IS_STATUS_ERROR(status))
5480 return -EINVAL;
5481 }
5482
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05305483 return 0;
5484}
5485
5486/**
5487 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
5488 * @wiphy: wiphy structure pointer
5489 * @wdev: Wireless device structure pointer
5490 * @data: Pointer to the data received
5491 * @data_len: Length of @data
5492 *
5493 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
5494 * driver.
5495 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
5496 * will initiate restart of sap.
5497 *
5498 * Return: 0 on success; errno on failure
5499 */
5500static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
5501 struct wireless_dev *wdev,
5502 const void *data, int data_len)
5503{
5504 int ret;
5505
5506 cds_ssr_protect(__func__);
5507 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
5508 wdev, data, data_len);
5509 cds_ssr_unprotect(__func__);
5510
5511 return ret;
5512}
5513
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305514#undef BPF_INVALID
5515#undef BPF_SET_RESET
5516#undef BPF_VERSION
5517#undef BPF_ID
5518#undef BPF_PACKET_SIZE
5519#undef BPF_CURRENT_OFFSET
5520#undef BPF_PROGRAM
5521#undef BPF_MAX
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
5523 {
5524 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5525 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
5526 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5527 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5528 .doit = is_driver_dfs_capable
5529 },
5530
5531#ifdef WLAN_FEATURE_NAN
5532 {
5533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5534 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
5535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5536 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5537 .doit = wlan_hdd_cfg80211_nan_request
5538 },
5539#endif
5540
5541#ifdef WLAN_FEATURE_STATS_EXT
5542 {
5543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
5545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5546 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5547 .doit = wlan_hdd_cfg80211_stats_ext_request
5548 },
5549#endif
5550#ifdef FEATURE_WLAN_EXTSCAN
5551 {
5552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
5554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5555 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5556 .doit = wlan_hdd_cfg80211_extscan_start
5557 },
5558 {
5559 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5560 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
5561 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5562 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5563 .doit = wlan_hdd_cfg80211_extscan_stop
5564 },
5565 {
5566 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5567 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
5568 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5569 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
5570 },
5571 {
5572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5573 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
5574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5575 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5576 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
5577 },
5578 {
5579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
5581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5582 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5583 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
5584 },
5585 {
5586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
5588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5589 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5590 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
5591 },
5592 {
5593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5594 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
5595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5596 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5597 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
5598 },
5599 {
5600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5601 .info.subcmd =
5602 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
5603 .flags =
5604 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
5605 WIPHY_VENDOR_CMD_NEED_RUNNING,
5606 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
5607 },
5608 {
5609 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5610 .info.subcmd =
5611 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
5612 .flags =
5613 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
5614 WIPHY_VENDOR_CMD_NEED_RUNNING,
5615 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
5616 },
5617 {
5618 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5619 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
5620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5621 WIPHY_VENDOR_CMD_NEED_NETDEV |
5622 WIPHY_VENDOR_CMD_NEED_RUNNING,
5623 .doit = wlan_hdd_cfg80211_set_epno_list
5624 },
5625#endif /* FEATURE_WLAN_EXTSCAN */
5626
5627#ifdef WLAN_FEATURE_LINK_LAYER_STATS
5628 {
5629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
5631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5632 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5633 .doit = wlan_hdd_cfg80211_ll_stats_clear
5634 },
5635
5636 {
5637 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5638 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
5639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5640 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5641 .doit = wlan_hdd_cfg80211_ll_stats_set
5642 },
5643
5644 {
5645 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5646 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
5647 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5648 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5649 .doit = wlan_hdd_cfg80211_ll_stats_get
5650 },
5651#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
5652#ifdef FEATURE_WLAN_TDLS
5653 {
5654 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5655 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
5656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5657 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5658 .doit = wlan_hdd_cfg80211_exttdls_enable
5659 },
5660 {
5661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
5663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5664 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
5665 .doit = wlan_hdd_cfg80211_exttdls_disable
5666 },
5667 {
5668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
5670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5671 .doit = wlan_hdd_cfg80211_exttdls_get_status
5672 },
5673#endif
5674 {
5675 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5676 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
5677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5678 .doit = wlan_hdd_cfg80211_get_supported_features
5679 },
5680 {
5681 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5682 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
5683 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
5684 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
5685 },
5686 {
5687 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5688 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
5689 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05305690 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005691 },
5692 {
5693 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5694 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
5695 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5696 WIPHY_VENDOR_CMD_NEED_NETDEV,
5697 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
5698 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07005699 {
5700 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5701 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
5702 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5703 WIPHY_VENDOR_CMD_NEED_NETDEV,
5704 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
5705 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005706 {
5707 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5708 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
5709 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5710 WIPHY_VENDOR_CMD_NEED_NETDEV |
5711 WIPHY_VENDOR_CMD_NEED_RUNNING,
5712 .doit = wlan_hdd_cfg80211_do_acs
5713 },
5714
5715 {
5716 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5717 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
5718 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5719 WIPHY_VENDOR_CMD_NEED_NETDEV,
5720 .doit = wlan_hdd_cfg80211_get_features
5721 },
5722#ifdef WLAN_FEATURE_ROAM_OFFLOAD
5723 {
5724 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5725 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
5726 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5727 WIPHY_VENDOR_CMD_NEED_NETDEV |
5728 WIPHY_VENDOR_CMD_NEED_RUNNING,
5729 .doit = wlan_hdd_cfg80211_keymgmt_set_key
5730 },
5731#endif
5732#ifdef FEATURE_WLAN_EXTSCAN
5733 {
5734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5735 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
5736 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5737 WIPHY_VENDOR_CMD_NEED_NETDEV |
5738 WIPHY_VENDOR_CMD_NEED_RUNNING,
5739 .doit = wlan_hdd_cfg80211_set_passpoint_list
5740 },
5741 {
5742 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5743 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
5744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5745 WIPHY_VENDOR_CMD_NEED_NETDEV |
5746 WIPHY_VENDOR_CMD_NEED_RUNNING,
5747 .doit = wlan_hdd_cfg80211_reset_passpoint_list
5748 },
5749 {
5750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
5752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5753 WIPHY_VENDOR_CMD_NEED_NETDEV |
5754 WIPHY_VENDOR_CMD_NEED_RUNNING,
5755 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
5756 },
5757 {
5758 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5759 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
5760 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5761 WIPHY_VENDOR_CMD_NEED_NETDEV |
5762 WIPHY_VENDOR_CMD_NEED_RUNNING,
5763 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
5764 },
5765#endif /* FEATURE_WLAN_EXTSCAN */
5766 {
5767 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5768 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
5769 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5770 WIPHY_VENDOR_CMD_NEED_NETDEV,
5771 .doit = wlan_hdd_cfg80211_get_wifi_info
5772 },
5773 {
5774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5775 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
5776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5777 WIPHY_VENDOR_CMD_NEED_NETDEV |
5778 WIPHY_VENDOR_CMD_NEED_RUNNING,
5779 .doit = wlan_hdd_cfg80211_wifi_configuration_set
5780 },
5781 {
5782 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5783 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
5784 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5785 WIPHY_VENDOR_CMD_NEED_NETDEV,
5786 .doit = wlan_hdd_cfg80211_set_ext_roam_params
5787 },
5788 {
5789 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5790 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
5791 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5792 WIPHY_VENDOR_CMD_NEED_NETDEV,
5793 .doit = wlan_hdd_cfg80211_wifi_logger_start
5794 },
5795 {
5796 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5797 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
5798 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5799 WIPHY_VENDOR_CMD_NEED_NETDEV,
5800 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
5801 },
5802 {
5803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5804 .info.subcmd =
5805 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
5806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5807 WIPHY_VENDOR_CMD_NEED_NETDEV |
5808 WIPHY_VENDOR_CMD_NEED_RUNNING,
5809 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
5810 },
5811 {
5812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5813 .info.subcmd =
5814 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
5815 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5816 WIPHY_VENDOR_CMD_NEED_NETDEV |
5817 WIPHY_VENDOR_CMD_NEED_RUNNING,
5818 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
5819 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07005820#ifdef WLAN_FEATURE_TSF
5821 {
5822 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5823 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
5824 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5825 WIPHY_VENDOR_CMD_NEED_NETDEV |
5826 WIPHY_VENDOR_CMD_NEED_RUNNING,
5827 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
5828 },
5829#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005830#ifdef FEATURE_WLAN_TDLS
5831 {
5832 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5833 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
5834 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5835 WIPHY_VENDOR_CMD_NEED_NETDEV |
5836 WIPHY_VENDOR_CMD_NEED_RUNNING,
5837 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
5838 },
5839#endif
5840#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5841 {
5842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
5844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5845 WIPHY_VENDOR_CMD_NEED_NETDEV |
5846 WIPHY_VENDOR_CMD_NEED_RUNNING,
5847 .doit = wlan_hdd_cfg80211_offloaded_packets
5848 },
5849#endif
5850 {
5851 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5852 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
5853 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5854 WIPHY_VENDOR_CMD_NEED_NETDEV |
5855 WIPHY_VENDOR_CMD_NEED_RUNNING,
5856 .doit = wlan_hdd_cfg80211_monitor_rssi
5857 },
5858 {
5859 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5860 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
5861 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5862 WIPHY_VENDOR_CMD_NEED_NETDEV |
5863 WIPHY_VENDOR_CMD_NEED_RUNNING,
5864 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
5865 },
5866#ifdef WLAN_FEATURE_MEMDUMP
5867 {
5868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
5870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5871 WIPHY_VENDOR_CMD_NEED_NETDEV |
5872 WIPHY_VENDOR_CMD_NEED_RUNNING,
5873 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
5874 },
5875#endif /* WLAN_FEATURE_MEMDUMP */
5876 {
5877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
5879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5880 WIPHY_VENDOR_CMD_NEED_NETDEV |
5881 WIPHY_VENDOR_CMD_NEED_RUNNING,
5882 .doit = wlan_hdd_cfg80211_vendor_scan
5883 },
5884
5885 /* OCB commands */
5886 {
5887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5888 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
5889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5890 WIPHY_VENDOR_CMD_NEED_NETDEV |
5891 WIPHY_VENDOR_CMD_NEED_RUNNING,
5892 .doit = wlan_hdd_cfg80211_ocb_set_config
5893 },
5894 {
5895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
5897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5898 WIPHY_VENDOR_CMD_NEED_NETDEV |
5899 WIPHY_VENDOR_CMD_NEED_RUNNING,
5900 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
5901 },
5902 {
5903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5904 .info.subcmd =
5905 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
5906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5907 WIPHY_VENDOR_CMD_NEED_NETDEV |
5908 WIPHY_VENDOR_CMD_NEED_RUNNING,
5909 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
5910 },
5911 {
5912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
5914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5915 WIPHY_VENDOR_CMD_NEED_NETDEV |
5916 WIPHY_VENDOR_CMD_NEED_RUNNING,
5917 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
5918 },
5919 {
5920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5921 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
5922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5923 WIPHY_VENDOR_CMD_NEED_NETDEV |
5924 WIPHY_VENDOR_CMD_NEED_RUNNING,
5925 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
5926 },
5927 {
5928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
5930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5931 WIPHY_VENDOR_CMD_NEED_NETDEV |
5932 WIPHY_VENDOR_CMD_NEED_RUNNING,
5933 .doit = wlan_hdd_cfg80211_dcc_get_stats
5934 },
5935 {
5936 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5937 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
5938 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5939 WIPHY_VENDOR_CMD_NEED_NETDEV |
5940 WIPHY_VENDOR_CMD_NEED_RUNNING,
5941 .doit = wlan_hdd_cfg80211_dcc_clear_stats
5942 },
5943 {
5944 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5945 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
5946 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5947 WIPHY_VENDOR_CMD_NEED_NETDEV |
5948 WIPHY_VENDOR_CMD_NEED_RUNNING,
5949 .doit = wlan_hdd_cfg80211_dcc_update_ndl
5950 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305951 {
5952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
5954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5955 WIPHY_VENDOR_CMD_NEED_NETDEV |
5956 WIPHY_VENDOR_CMD_NEED_RUNNING,
5957 .doit = wlan_hdd_cfg80211_get_link_properties
5958 },
Peng Xu278d0122015-09-24 16:34:17 -07005959 {
5960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
5961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5962 WIPHY_VENDOR_CMD_NEED_NETDEV |
5963 WIPHY_VENDOR_CMD_NEED_RUNNING,
5964 .doit = wlan_hdd_cfg80211_set_ota_test
5965 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08005966#ifdef FEATURE_LFR_SUBNET_DETECTION
5967 {
5968 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5969 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
5970 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5971 WIPHY_VENDOR_CMD_NEED_NETDEV |
5972 WIPHY_VENDOR_CMD_NEED_RUNNING,
5973 .doit = wlan_hdd_cfg80211_set_gateway_params
5974 },
5975#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07005976 {
5977 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
5978 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5979 WIPHY_VENDOR_CMD_NEED_NETDEV |
5980 WIPHY_VENDOR_CMD_NEED_RUNNING,
5981 .doit = wlan_hdd_cfg80211_txpower_scale
5982 },
5983 {
5984 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5985 .info.subcmd =
5986 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
5987 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5988 WIPHY_VENDOR_CMD_NEED_NETDEV |
5989 WIPHY_VENDOR_CMD_NEED_RUNNING,
5990 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
5991 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305992 {
5993 .info.vendor_id = QCA_NL80211_VENDOR_ID,
5994 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
5995 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
5996 WIPHY_VENDOR_CMD_NEED_NETDEV |
5997 WIPHY_VENDOR_CMD_NEED_RUNNING,
5998 .doit = wlan_hdd_cfg80211_bpf_offload
5999 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306000 {
6001 .info.vendor_id = QCA_NL80211_VENDOR_ID,
6002 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
6003 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
6004 WIPHY_VENDOR_CMD_NEED_NETDEV |
6005 WIPHY_VENDOR_CMD_NEED_RUNNING,
6006 .doit = wlan_hdd_cfg80211_sap_configuration_set
6007 },
6008
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006009};
6010
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006011/**
6012 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
6013 * @priv_size: Size of the hdd context.
6014 *
6015 * Allocate wiphy context and hdd context.
6016 *
6017 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006018 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006019hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020{
6021 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006022 hdd_context_t *hdd_ctx;
6023
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006024 ENTER();
6025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
6027
6028 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006029 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030 return NULL;
6031 }
6032
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08006033 hdd_ctx = wiphy_priv(wiphy);
6034
6035 hdd_ctx->wiphy = wiphy;
6036
6037 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006038}
6039
6040/*
6041 * FUNCTION: wlan_hdd_cfg80211_update_band
6042 * This function is called from the supplicant through a
6043 * private ioctl to change the band value
6044 */
6045int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
6046{
6047 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07006048 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049
6050 ENTER();
6051
6052 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
6053
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08006054 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006055 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056
6057 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
6058 struct ieee80211_supported_band *band = wiphy->bands[i];
6059
6060 channelEnabledState =
6061 cds_get_channel_state(band->channels[j].
6062 hw_value);
6063
6064 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
6065 /* 5G only */
6066#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
6067 /* Enable Social channels for P2P */
6068 if (WLAN_HDD_IS_SOCIAL_CHANNEL
6069 (band->channels[j].center_freq)
6070 && CHANNEL_STATE_ENABLE ==
6071 channelEnabledState)
6072 band->channels[j].flags &=
6073 ~IEEE80211_CHAN_DISABLED;
6074 else
6075#endif
6076 band->channels[j].flags |=
6077 IEEE80211_CHAN_DISABLED;
6078 continue;
6079 } else if (IEEE80211_BAND_5GHZ == i &&
6080 eCSR_BAND_24 == eBand) {
6081 /* 2G only */
6082 band->channels[j].flags |=
6083 IEEE80211_CHAN_DISABLED;
6084 continue;
6085 }
6086
Amar Singhal6842e8f2016-02-23 16:30:32 -08006087 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006088 band->channels[j].flags &=
6089 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006090 }
6091 }
6092 return 0;
6093}
6094
6095/*
6096 * FUNCTION: wlan_hdd_cfg80211_init
6097 * This function is called by hdd_wlan_startup()
6098 * during initialization.
6099 * This function is used to initialize and register wiphy structure.
6100 */
6101int wlan_hdd_cfg80211_init(struct device *dev,
6102 struct wiphy *wiphy, struct hdd_config *pCfg)
6103{
6104 int i, j;
6105 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6106
6107 ENTER();
6108
6109 /* Now bind the underlying wlan device with wiphy */
6110 set_wiphy_dev(wiphy, dev);
6111
6112 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
6113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006114#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6115 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07006116 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006117#else
6118 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07006119 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006120#endif
6121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006122 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
6123 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
6124 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
6125#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
6126 | WIPHY_FLAG_4ADDR_STATION
6127#endif
6128 | WIPHY_FLAG_OFFCHAN_TX;
6129
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006130#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
6131 wiphy->wowlan = &wowlan_support_cfg80211_init;
6132#else
6133 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
6134 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
6135 wiphy->wowlan.pattern_min_len = 1;
6136 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
6137#endif
6138
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07006139 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006140#ifdef FEATURE_WLAN_ESE
6141 || pCfg->isEseIniFeatureEnabled
6142#endif
6143 ) {
6144 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
6145 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006146#ifdef FEATURE_WLAN_TDLS
6147 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
6148 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
6149#endif
6150
6151 wiphy->features |= NL80211_FEATURE_HT_IBSS;
6152
6153#ifdef FEATURE_WLAN_SCAN_PNO
6154 if (pCfg->configPNOScanSupport) {
6155 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6156 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
6157 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
6158 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07006159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
6160 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
6161#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006162 }
6163#endif /*FEATURE_WLAN_SCAN_PNO */
6164
6165#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05306166 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006167#endif
6168
6169 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
6170 driver can still register regulatory callback and
6171 it will get regulatory settings in wiphy->band[], but
6172 driver need to determine what to do with both
6173 regulatory settings */
6174
6175 wiphy->reg_notifier = hdd_reg_notifier;
6176
6177#if defined QCA_WIFI_FTM
6178}
6179#endif
6180
6181 wiphy->max_scan_ssids = MAX_SCAN_SSID;
6182
6183 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
6184
6185 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
6186
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07006187 if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE) {
6188 /* Supports STATION & AD-HOC modes right now */
6189 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
6190 | BIT(NL80211_IFTYPE_ADHOC)
6191 | BIT(NL80211_IFTYPE_P2P_CLIENT)
6192 | BIT(NL80211_IFTYPE_P2P_GO)
6193 | BIT(NL80211_IFTYPE_AP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006194
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07006195 if (pCfg->advertiseConcurrentOperation) {
6196 if (pCfg->enableMCC) {
6197 int i;
6198
6199 for (i = 0;
6200 i < ARRAY_SIZE(wlan_hdd_iface_combination);
6201 i++) {
6202 if (!pCfg->allowMCCGODiffBI)
6203 wlan_hdd_iface_combination[i].
6204 beacon_int_infra_match = true;
6205 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006206 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07006207 wiphy->n_iface_combinations =
6208 ARRAY_SIZE(wlan_hdd_iface_combination);
6209 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006210 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07006211 } else {
6212 wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006213 wiphy->n_iface_combinations =
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07006214 ARRAY_SIZE(wlan_hdd_mon_iface);
6215 wiphy->iface_combinations = wlan_hdd_mon_iface;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006216 }
6217
6218 /* Before registering we need to update the ht capabilitied based
6219 * on ini values*/
6220 if (!pCfg->ShortGI20MhzEnable) {
6221 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
6222 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006223 }
6224
6225 if (!pCfg->ShortGI40MhzEnable) {
6226 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
6227 }
6228
6229 if (!pCfg->nChannelBondingMode5GHz) {
6230 wlan_hdd_band_5_ghz.ht_cap.cap &=
6231 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
6232 }
6233
Abhishek Singhf512bf32016-05-04 16:47:46 +05306234 /*
6235 * In case of static linked driver at the time of driver unload,
6236 * module exit doesn't happens. Module cleanup helps in cleaning
6237 * of static memory.
6238 * If driver load happens statically, at the time of driver unload,
6239 * wiphy flags don't get reset because of static memory.
6240 * It's better not to store channel in static memory.
6241 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006242 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05306243 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
6244 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
6245 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
6246 hdd_err("Not enough memory to allocate channels");
6247 return -ENOMEM;
6248 }
6249 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
6250 &hdd_channels_2_4_ghz[0],
6251 sizeof(hdd_channels_2_4_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006252 if (true == hdd_is_5g_supported(pHddCtx)) {
6253 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05306254 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
6255 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
6256 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
6257 hdd_err("Not enough memory to allocate channels");
6258 qdf_mem_free(wiphy->
6259 bands[IEEE80211_BAND_2GHZ]->channels);
6260 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
6261 return -ENOMEM;
6262 }
6263 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
6264 &hdd_channels_5_ghz[0],
6265 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006266 }
6267
6268 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
6269
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08006270 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006271 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006272
6273 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
6274 struct ieee80211_supported_band *band = wiphy->bands[i];
6275
6276 if (IEEE80211_BAND_2GHZ == i &&
6277 eCSR_BAND_5G == pCfg->nBandCapability) {
6278 /* 5G only */
6279#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
6280 /* Enable social channels for P2P */
6281 if (WLAN_HDD_IS_SOCIAL_CHANNEL
6282 (band->channels[j].center_freq))
6283 band->channels[j].flags &=
6284 ~IEEE80211_CHAN_DISABLED;
6285 else
6286#endif
6287 band->channels[j].flags |=
6288 IEEE80211_CHAN_DISABLED;
6289 continue;
6290 } else if (IEEE80211_BAND_5GHZ == i &&
6291 eCSR_BAND_24 == pCfg->nBandCapability) {
6292 /* 2G only */
6293 band->channels[j].flags |=
6294 IEEE80211_CHAN_DISABLED;
6295 continue;
6296 }
6297 }
6298 }
6299 /*Initialise the supported cipher suite details */
6300 wiphy->cipher_suites = hdd_cipher_suites;
6301 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
6302
6303 /*signal strength in mBm (100*dBm) */
6304 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
6305 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
6306
Anurag Chouhan6d760662016-02-20 16:05:43 +05306307 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006308 wiphy->n_vendor_commands =
6309 ARRAY_SIZE(hdd_wiphy_vendor_commands);
6310 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
6311
6312 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
6313 wiphy->n_vendor_events =
6314 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
6315 }
6316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006317 if (pCfg->enableDFSMasterCap) {
6318 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
6319 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006320
6321 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
6322
6323#ifdef QCA_HT_2040_COEX
6324 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
6325#endif
6326
Abhishek Singh1bdb1572015-10-16 16:24:19 +05306327 hdd_add_channel_switch_support(&wiphy->flags);
6328
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006329 EXIT();
6330 return 0;
6331}
6332
Abhishek Singhf512bf32016-05-04 16:47:46 +05306333/**
6334 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
6335 * @ wiphy: the wiphy to validate against
6336 *
6337 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05306338 * memory allocated in wlan_hdd_cfg80211_init also
6339 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05306340 *
6341 * Return: void
6342 */
6343void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
6344{
6345 int i;
6346
6347 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
6348 if (NULL != wiphy->bands[i] &&
6349 (NULL != wiphy->bands[i]->channels)) {
6350 qdf_mem_free(wiphy->bands[i]->channels);
6351 wiphy->bands[i]->channels = NULL;
6352 }
6353 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05306354 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05306355}
6356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006357/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306358 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006359 * initialization. In wlan_hdd_cfg80211_init, only the
6360 * default values will be initialized. The final initialization
6361 * of all required members can be done here.
6362 */
6363void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
6364{
6365 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
6366}
6367
6368/* In this function we are registering wiphy. */
6369int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
6370{
6371 ENTER();
6372 /* Register our wiphy dev with cfg80211 */
6373 if (0 > wiphy_register(wiphy)) {
6374 /* print error */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306375 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: wiphy register failed",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006376 __func__);
6377 return -EIO;
6378 }
6379
6380 EXIT();
6381 return 0;
6382}
6383
6384/*
6385 HDD function to update wiphy capability based on target offload status.
6386
6387 wlan_hdd_cfg80211_init() does initialization of all wiphy related
6388 capability even before downloading firmware to the target. In discrete
6389 case, host will get know certain offload capability (say sched_scan
6390 caps) only after downloading firmware to the target and target boots up.
6391 This function is used to override setting done in wlan_hdd_cfg80211_init()
6392 based on target capability.
6393 */
6394void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
6395{
6396#ifdef FEATURE_WLAN_SCAN_PNO
6397 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
6398 struct hdd_config *pCfg = pHddCtx->config;
6399
6400 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
6401 * control comes here. Here just we need to clear it if firmware doesn't
6402 * have PNO support. */
6403 if (!pCfg->PnoOffload) {
6404 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6405 wiphy->max_sched_scan_ssids = 0;
6406 wiphy->max_match_sets = 0;
6407 wiphy->max_sched_scan_ie_len = 0;
6408 }
6409#endif
6410}
6411
6412/* This function registers for all frame which supplicant is interested in */
6413void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
6414{
6415 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6416 /* Register for all P2P action, public action etc frames */
6417 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
6418
6419 ENTER();
6420
Abhishek Singh7996eb72015-12-30 17:24:02 +05306421 /* Register frame indication call back */
6422 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
6423
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006424 /* Right now we are registering these frame when driver is getting
6425 initialized. Once we will move to 2.6.37 kernel, in which we have
6426 frame register ops, we will move this code as a part of that */
6427 /* GAS Initial Request */
6428 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6429 (uint8_t *) GAS_INITIAL_REQ,
6430 GAS_INITIAL_REQ_SIZE);
6431
6432 /* GAS Initial Response */
6433 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6434 (uint8_t *) GAS_INITIAL_RSP,
6435 GAS_INITIAL_RSP_SIZE);
6436
6437 /* GAS Comeback Request */
6438 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6439 (uint8_t *) GAS_COMEBACK_REQ,
6440 GAS_COMEBACK_REQ_SIZE);
6441
6442 /* GAS Comeback Response */
6443 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6444 (uint8_t *) GAS_COMEBACK_RSP,
6445 GAS_COMEBACK_RSP_SIZE);
6446
6447 /* P2P Public Action */
6448 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6449 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
6450 P2P_PUBLIC_ACTION_FRAME_SIZE);
6451
6452 /* P2P Action */
6453 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6454 (uint8_t *) P2P_ACTION_FRAME,
6455 P2P_ACTION_FRAME_SIZE);
6456
6457 /* WNM BSS Transition Request frame */
6458 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6459 (uint8_t *) WNM_BSS_ACTION_FRAME,
6460 WNM_BSS_ACTION_FRAME_SIZE);
6461
6462 /* WNM-Notification */
6463 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
6464 (uint8_t *) WNM_NOTIFICATION_FRAME,
6465 WNM_NOTIFICATION_FRAME_SIZE);
6466}
6467
6468void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
6469{
6470 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6471 /* Register for all P2P action, public action etc frames */
6472 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
6473
6474 ENTER();
6475
6476 /* Right now we are registering these frame when driver is getting
6477 initialized. Once we will move to 2.6.37 kernel, in which we have
6478 frame register ops, we will move this code as a part of that */
6479 /* GAS Initial Request */
6480
6481 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6482 (uint8_t *) GAS_INITIAL_REQ,
6483 GAS_INITIAL_REQ_SIZE);
6484
6485 /* GAS Initial Response */
6486 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6487 (uint8_t *) GAS_INITIAL_RSP,
6488 GAS_INITIAL_RSP_SIZE);
6489
6490 /* GAS Comeback Request */
6491 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6492 (uint8_t *) GAS_COMEBACK_REQ,
6493 GAS_COMEBACK_REQ_SIZE);
6494
6495 /* GAS Comeback Response */
6496 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6497 (uint8_t *) GAS_COMEBACK_RSP,
6498 GAS_COMEBACK_RSP_SIZE);
6499
6500 /* P2P Public Action */
6501 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6502 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
6503 P2P_PUBLIC_ACTION_FRAME_SIZE);
6504
6505 /* P2P Action */
6506 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
6507 (uint8_t *) P2P_ACTION_FRAME,
6508 P2P_ACTION_FRAME_SIZE);
6509
6510 /* WNM-Notification */
6511 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
6512 (uint8_t *) WNM_NOTIFICATION_FRAME,
6513 WNM_NOTIFICATION_FRAME_SIZE);
6514}
6515
6516#ifdef FEATURE_WLAN_WAPI
6517void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
6518 const uint8_t *mac_addr, const uint8_t *key,
6519 int key_Len)
6520{
6521 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6522 tCsrRoamSetKey setKey;
6523 bool isConnected = true;
6524 int status = 0;
6525 uint32_t roamId = 0xFF;
6526 uint8_t *pKeyPtr = NULL;
6527 int n = 0;
6528
6529 hddLog(LOG1, "Device_mode %s(%d)",
6530 hdd_device_mode_to_string(pAdapter->device_mode),
6531 pAdapter->device_mode);
6532
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306533 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006534 setKey.keyId = key_index; /* Store Key ID */
6535 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
6536 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
6537 setKey.paeRole = 0; /* the PAE role */
6538 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05306539 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006540 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306541 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006542 }
6543 setKey.keyLength = key_Len;
6544 pKeyPtr = setKey.Key;
6545 memcpy(pKeyPtr, key, key_Len);
6546
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306547 hddLog(QDF_TRACE_LEVEL_INFO, "%s: WAPI KEY LENGTH:0x%04x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006548 __func__, key_Len);
6549 for (n = 0; n < key_Len; n++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306550 hddLog(QDF_TRACE_LEVEL_INFO, "%s WAPI KEY Data[%d]:%02x ",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006551 __func__, n, setKey.Key[n]);
6552
6553 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
6554 if (isConnected) {
6555 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
6556 pAdapter->sessionId, &setKey, &roamId);
6557 }
6558 if (status != 0) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306559 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006560 "[%4d] sme_roam_set_key returned ERROR status= %d",
6561 __LINE__, status);
6562 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
6563 }
6564}
6565#endif /* FEATURE_WLAN_WAPI */
6566
6567uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
6568 uint8_t eid)
6569{
6570 int left = length;
6571 uint8_t *ptr = (uint8_t *)ies_ptr;
6572 uint8_t elem_id, elem_len;
6573
6574 while (left >= 2) {
6575 elem_id = ptr[0];
6576 elem_len = ptr[1];
6577 left -= 2;
6578 if (elem_len > left) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306579 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006580 FL("Invalid IEs eid = %d elem_len=%d left=%d"),
6581 eid, elem_len, left);
6582 return NULL;
6583 }
6584 if (elem_id == eid) {
6585 return ptr;
6586 }
6587
6588 left -= elem_len;
6589 ptr += (elem_len + 2);
6590 }
6591 return NULL;
6592}
6593
6594/*
6595 * FUNCTION: wlan_hdd_validate_operation_channel
6596 * called by wlan_hdd_cfg80211_start_bss() and
6597 * wlan_hdd_set_channel()
6598 * This function validates whether given channel is part of valid
6599 * channel list.
6600 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306601QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006602 int channel)
6603{
6604
6605 uint32_t num_ch = 0;
6606 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
6607 u32 indx = 0;
6608 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
6609 uint8_t fValidChannel = false, count = 0;
6610 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
6611
6612 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6613
6614 if (hdd_pConfig_ini->sapAllowAllChannel) {
6615 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08006616 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07006617 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006618 fValidChannel = true;
6619 break;
6620 }
6621 }
6622 if (fValidChannel != true) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306623 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006624 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306625 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006626 }
6627 } else {
6628 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
6629 valid_ch, &num_ch)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306630 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006631 "%s: failed to get valid channel list",
6632 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306633 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006634 }
6635 for (indx = 0; indx < num_ch; indx++) {
6636 if (channel == valid_ch[indx]) {
6637 break;
6638 }
6639 }
6640
6641 if (indx >= num_ch) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306642 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006643 "%s: Invalid Channel [%d]", __func__, channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306644 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006645 }
6646 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306647 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006648
6649}
6650
6651#ifdef DHCP_SERVER_OFFLOAD
6652static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
6653{
6654 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
6655 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
6656 uint8_t numEntries = 0;
6657 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
6658 uint8_t num;
6659 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306660 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006661 if (NULL == pDhcpSrvInfo) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306662 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006663 "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
6664 return;
6665 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306666 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006667 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
6668 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
6669 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
6670 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
6671 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
6672 if (numEntries != IPADDR_NUM_ENTRIES) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306673 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006674 "%s: incorrect IP address (%s) assigned for DHCP server!",
6675 __func__, pHddCtx->config->dhcpServerIP);
6676 goto end;
6677 }
6678 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306679 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006680 "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
6681 __func__, pHddCtx->config->dhcpServerIP);
6682 goto end;
6683 }
6684 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306685 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006686 "%s: invalid IP address (%s)! The last field must be less than 100!",
6687 __func__, pHddCtx->config->dhcpServerIP);
6688 goto end;
6689 }
6690 for (num = 0; num < numEntries; num++) {
6691 temp = srv_ip[num];
6692 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
6693 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306694 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006695 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306696 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006697 "%s: sme_setDHCPSrvOffload fail!", __func__);
6698 goto end;
6699 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306700 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006701 "%s: enable DHCP Server offload successfully!", __func__);
6702end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306703 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006704 return;
6705}
6706#endif /* DHCP_SERVER_OFFLOAD */
6707
6708static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6709 struct net_device *dev,
6710 struct bss_parameters *params)
6711{
6712 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6713 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6714 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306715 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006716
6717 ENTER();
6718
Anurag Chouhan6d760662016-02-20 16:05:43 +05306719 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006720 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6721 return -EINVAL;
6722 }
6723
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306724 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006725 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
6726 pAdapter->sessionId, params->ap_isolate));
6727 hddLog(LOG1, FL("Device_mode %s(%d), ap_isolate = %d"),
6728 hdd_device_mode_to_string(pAdapter->device_mode),
6729 pAdapter->device_mode, params->ap_isolate);
6730
6731 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6732 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306733 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006734 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006735
Krunal Sonib4326f22016-03-10 13:05:51 -08006736 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
6737 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006738 return -EOPNOTSUPP;
6739 }
6740
6741 /* ap_isolate == -1 means that in change bss, upper layer doesn't
6742 * want to update this parameter */
6743 if (-1 != params->ap_isolate) {
6744 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
6745 !!params->ap_isolate;
6746
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306747 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006748 pAdapter->sessionId,
6749 pAdapter->sessionCtx.
6750 ap.
6751 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05306752 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006753 ret = -EINVAL;
6754 }
6755 }
6756
6757 EXIT();
6758 return ret;
6759}
6760
Krunal Soni8c37e322016-02-03 16:08:37 -08006761/**
6762 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
6763 * @ndev: pointer to net device provided by supplicant
6764 * @type: type of the interface, upper layer wanted to change
6765 *
6766 * Upper layer provides the new interface mode that needs to be changed
6767 * for given net device
6768 *
6769 * Return: success or failure in terms of integer value
6770 */
6771static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006772 enum nl80211_iftype type)
6773{
Krunal Soni8c37e322016-02-03 16:08:37 -08006774 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6775 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6776 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006777 hdd_wext_state_t *wext;
6778 struct wireless_dev *wdev;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306779 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006780
6781 ENTER();
6782
Krunal Soni8c37e322016-02-03 16:08:37 -08006783 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006784 hddLog(LOG1, FL("ACS is in progress, don't change iface!"));
6785 return 0;
6786 }
6787
6788 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08006789 hdd_stop_adapter(hdd_ctx, adapter, true);
6790 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006791 wdev->iftype = type;
6792 /*Check for sub-string p2p to confirm its a p2p interface */
6793 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08006794 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006795 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006796 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08006797 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08006798 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006799 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08006800 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006801 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08006802 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006803 }
Krunal Soni8c37e322016-02-03 16:08:37 -08006804 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
6805 hdd_set_station_ops(adapter->dev);
6806 status = hdd_init_station_mode(adapter);
6807 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
6808 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006809 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08006810 adapter->scan_info.scanAddIE.length;
6811 if (type == NL80211_IFTYPE_ADHOC) {
6812 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
6813 wext->roamProfile.phyMode =
6814 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
6815 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006816 EXIT();
6817 return status;
6818}
6819
6820static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
6821 struct net_device *dev,
6822 struct bss_parameters *params)
6823{
6824 int ret;
6825
6826 cds_ssr_protect(__func__);
6827 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
6828 cds_ssr_unprotect(__func__);
6829
6830 return ret;
6831}
6832
6833/* FUNCTION: wlan_hdd_change_country_code_cd
6834 * to wait for contry code completion
6835 */
6836void *wlan_hdd_change_country_code_cb(void *pAdapter)
6837{
6838 hdd_adapter_t *call_back_pAdapter = pAdapter;
6839 complete(&call_back_pAdapter->change_country_code);
6840 return NULL;
6841}
6842
Rajeev Kumar98edb772016-01-19 12:42:19 -08006843/**
6844 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
6845 * @wiphy: Pointer to the wiphy structure
6846 * @ndev: Pointer to the net device
6847 * @type: Interface type
6848 * @flags: Flags for change interface
6849 * @params: Pointer to change interface parameters
6850 *
6851 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006852 */
6853static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
6854 struct net_device *ndev,
6855 enum nl80211_iftype type,
6856 u32 *flags,
6857 struct vif_params *params)
6858{
6859 struct wireless_dev *wdev;
6860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6861 hdd_context_t *pHddCtx;
6862 tCsrRoamProfile *pRoamProfile = NULL;
6863 eCsrRoamBssType LastBSSType;
6864 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306865 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006866 int status;
6867
6868 ENTER();
6869
Anurag Chouhan6d760662016-02-20 16:05:43 +05306870 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006871 hddLog(LOGE, FL("Command not allowed in FTM mode"));
6872 return -EINVAL;
6873 }
6874
6875 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6876 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306877 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006878 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006879
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306880 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006881 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
6882 pAdapter->sessionId, type));
6883
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306884 hddLog(QDF_TRACE_LEVEL_INFO, FL("Device_mode = %d, IFTYPE = 0x%x"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006885 pAdapter->device_mode, type);
6886
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006887 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006888 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
6889 0, HW_MODE_20_MHZ)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306890 hddLog(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006891 FL("This concurrency combination is not allowed"));
6892 return -EINVAL;
6893 }
6894
6895 pConfig = pHddCtx->config;
6896 wdev = ndev->ieee80211_ptr;
6897
6898 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08006899 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006900
6901 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
6902
Krunal Sonib4326f22016-03-10 13:05:51 -08006903 if ((pAdapter->device_mode == QDF_STA_MODE) ||
6904 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
6905 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
6906 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006907 hdd_wext_state_t *pWextState =
6908 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6909
6910 pRoamProfile = &pWextState->roamProfile;
6911 LastBSSType = pRoamProfile->BSSType;
6912
6913 switch (type) {
6914 case NL80211_IFTYPE_STATION:
6915 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08006916 case NL80211_IFTYPE_ADHOC:
6917 if (type == NL80211_IFTYPE_ADHOC) {
6918 wlan_hdd_tdls_exit(pAdapter);
6919 hdd_deregister_tx_flow_control(pAdapter);
6920 hddLog(LOG1,
6921 FL("Setting interface Type to ADHOC"));
6922 }
6923 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
6924 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306925 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006926 return -EINVAL;
6927
Krunal Soni8c37e322016-02-03 16:08:37 -08006928 /*
6929 * for ibss interface type flow control is not required
6930 * so don't register tx flow control
6931 */
6932 if (type != NL80211_IFTYPE_ADHOC)
6933 hdd_register_tx_flow_control(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006934 hdd_tx_resume_timer_expired_handler,
6935 hdd_tx_resume_cb);
6936
6937 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006938 case NL80211_IFTYPE_AP:
6939 case NL80211_IFTYPE_P2P_GO:
6940 {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05306941 hddLog(QDF_TRACE_LEVEL_INFO_HIGH,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006942 FL("Setting interface Type to %s"),
6943 (type ==
6944 NL80211_IFTYPE_AP) ? "SoftAP" :
6945 "P2pGo");
6946
6947 /* Cancel any remain on channel for GO mode */
6948 if (NL80211_IFTYPE_P2P_GO == type) {
6949 wlan_hdd_cancel_existing_remain_on_channel
6950 (pAdapter);
6951 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006952 hdd_stop_adapter(pHddCtx, pAdapter, true);
6953
6954 /* De-init the adapter */
6955 hdd_deinit_adapter(pHddCtx, pAdapter, true);
6956 memset(&pAdapter->sessionCtx, 0,
6957 sizeof(pAdapter->sessionCtx));
6958 pAdapter->device_mode =
6959 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08006960 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
6961 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006962
6963 /*
6964 * Fw will take care incase of concurrency
6965 */
6966
Krunal Sonib4326f22016-03-10 13:05:51 -08006967 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006968 && (pConfig->apRandomBssidEnabled)) {
6969 /* To meet Android requirements create a randomized
6970 MAC address of the form 02:1A:11:Fx:xx:xx */
6971 get_random_bytes(&ndev->dev_addr[3], 3);
6972 ndev->dev_addr[0] = 0x02;
6973 ndev->dev_addr[1] = 0x1A;
6974 ndev->dev_addr[2] = 0x11;
6975 ndev->dev_addr[3] |= 0xF0;
6976 memcpy(pAdapter->macAddressCurrent.
6977 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306978 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006979 pr_info("wlan: Generated HotSpot BSSID "
6980 MAC_ADDRESS_STR "\n",
6981 MAC_ADDR_ARRAY(ndev->dev_addr));
6982 }
6983
6984 hdd_set_ap_ops(pAdapter->dev);
6985
6986 vstatus = hdd_init_ap_mode(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306987 if (vstatus != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006988 hddLog(LOGP,
6989 FL
6990 ("Error initializing the ap mode"));
6991 return -EINVAL;
6992 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006993
6994 hdd_register_tx_flow_control(pAdapter,
6995 hdd_softap_tx_resume_timer_expired_handler,
6996 hdd_softap_tx_resume_cb);
6997
6998 /* Interface type changed update in wiphy structure */
6999 if (wdev) {
7000 wdev->iftype = type;
7001 } else {
7002 hddLog(LOGE,
7003 FL("Wireless dev is NULL"));
7004 return -EINVAL;
7005 }
7006 goto done;
7007 }
7008
7009 default:
7010 hddLog(LOGE, FL("Unsupported interface type (%d)"),
7011 type);
7012 return -EOPNOTSUPP;
7013 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007014 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
7015 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007016 switch (type) {
7017 case NL80211_IFTYPE_STATION:
7018 case NL80211_IFTYPE_P2P_CLIENT:
7019 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08007020 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
7021 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307022 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007023 return status;
7024
7025 if ((NL80211_IFTYPE_P2P_CLIENT == type) ||
7026 (NL80211_IFTYPE_STATION == type)) {
7027
7028 hdd_register_tx_flow_control(pAdapter,
7029 hdd_tx_resume_timer_expired_handler,
7030 hdd_tx_resume_cb);
7031 }
7032 goto done;
7033
7034 case NL80211_IFTYPE_AP:
7035 case NL80211_IFTYPE_P2P_GO:
7036 wdev->iftype = type;
7037 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08007038 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007039
7040 hdd_register_tx_flow_control(pAdapter,
7041 hdd_softap_tx_resume_timer_expired_handler,
7042 hdd_softap_tx_resume_cb);
7043 goto done;
7044
7045 default:
7046 hddLog(LOGE, FL("Unsupported interface type(%d)"),
7047 type);
7048 return -EOPNOTSUPP;
7049 }
7050 } else {
7051 hddLog(LOGE, FL("Unsupported device mode(%d)"),
7052 pAdapter->device_mode);
7053 return -EOPNOTSUPP;
7054 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007055done:
7056 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08007057 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007059 wlan_hdd_send_all_scan_intf_info(pHddCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007060
7061 EXIT();
7062 return 0;
7063}
7064
Rajeev Kumar98edb772016-01-19 12:42:19 -08007065/**
7066 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
7067 * @wiphy: Pointer to the wiphy structure
7068 * @ndev: Pointer to the net device
7069 * @type: Interface type
7070 * @flags: Flags for change interface
7071 * @params: Pointer to change interface parameters
7072 *
7073 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007074 */
7075static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
7076 struct net_device *ndev,
7077 enum nl80211_iftype type,
7078 u32 *flags,
7079 struct vif_params *params)
7080{
7081 int ret;
7082
7083 cds_ssr_protect(__func__);
7084 ret =
7085 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
7086 cds_ssr_unprotect(__func__);
7087
7088 return ret;
7089}
7090
7091#ifdef FEATURE_WLAN_TDLS
7092static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
7093 int index, uint8_t match)
7094{
7095 int i;
7096 for (i = 0; i < index; i++) {
7097 if (arr[i] == match)
7098 return true;
7099 }
7100 return false;
7101}
7102#endif
7103
7104/**
7105 * __wlan_hdd_change_station() - change station
7106 * @wiphy: Pointer to the wiphy structure
7107 * @dev: Pointer to the net device.
7108 * @mac: bssid
7109 * @params: Pointer to station parameters
7110 *
7111 * Return: 0 for success, error number on failure.
7112 */
7113#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7114static int __wlan_hdd_change_station(struct wiphy *wiphy,
7115 struct net_device *dev,
7116 const uint8_t *mac,
7117 struct station_parameters *params)
7118#else
7119static int __wlan_hdd_change_station(struct wiphy *wiphy,
7120 struct net_device *dev,
7121 uint8_t *mac,
7122 struct station_parameters *params)
7123#endif
7124{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307125 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007126 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7127 hdd_context_t *pHddCtx;
7128 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307129 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007130#ifdef FEATURE_WLAN_TDLS
7131 tCsrStaParams StaParams = { 0 };
7132 uint8_t isBufSta = 0;
7133 uint8_t isOffChannelSupported = 0;
7134#endif
7135 int ret;
7136
7137 ENTER();
7138
Anurag Chouhan6d760662016-02-20 16:05:43 +05307139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007140 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7141 return -EINVAL;
7142 }
7143
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307144 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007145 TRACE_CODE_HDD_CHANGE_STATION,
7146 pAdapter->sessionId, params->listen_interval));
7147
7148 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7149 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307150 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007151 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007152
7153 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7154
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307155 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007156
Krunal Sonib4326f22016-03-10 13:05:51 -08007157 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
7158 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007159 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
7160 status =
7161 hdd_softap_change_sta_state(pAdapter,
7162 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08007163 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307165 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307166 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007167 FL
7168 ("Not able to change TL state to AUTHENTICATED"));
7169 return -EINVAL;
7170 }
7171 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007172 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
7173 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007174#ifdef FEATURE_WLAN_TDLS
7175 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
7176 StaParams.capability = params->capability;
7177 StaParams.uapsd_queues = params->uapsd_queues;
7178 StaParams.max_sp = params->max_sp;
7179
7180 /* Convert (first channel , number of channels) tuple to
7181 * the total list of channels. This goes with the assumption
7182 * that if the first channel is < 14, then the next channels
7183 * are an incremental of 1 else an incremental of 4 till the number
7184 * of channels.
7185 */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307186 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007187 "%s: params->supported_channels_len: %d",
7188 __func__, params->supported_channels_len);
7189 if (0 != params->supported_channels_len) {
7190 int i = 0, j = 0, k = 0, no_of_channels = 0;
7191 int num_unique_channels;
7192 int next;
7193 for (i = 0;
7194 i < params->supported_channels_len
7195 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
7196 int wifi_chan_index;
7197 if (!wlan_hdd_is_duplicate_channel
7198 (StaParams.supported_channels, j,
7199 params->supported_channels[i])) {
7200 StaParams.
7201 supported_channels[j] =
7202 params->
7203 supported_channels[i];
7204 } else {
7205 continue;
7206 }
7207 wifi_chan_index =
7208 ((StaParams.supported_channels[j] <=
7209 HDD_CHANNEL_14) ? 1 : 4);
7210 no_of_channels =
7211 params->supported_channels[i + 1];
7212
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307213 QDF_TRACE(QDF_MODULE_ID_HDD,
7214 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007215 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d",
7216 __func__, i, j, k, j,
7217 StaParams.
7218 supported_channels[j],
7219 wifi_chan_index,
7220 no_of_channels);
7221 for (k = 1; k <= no_of_channels &&
7222 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
7223 k++) {
7224 next =
7225 StaParams.
7226 supported_channels[j] +
7227 wifi_chan_index;
7228 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
7229 StaParams.
7230 supported_channels[j
7231 +
7232 1]
7233 = next;
7234 } else {
7235 continue;
7236 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307237 QDF_TRACE(QDF_MODULE_ID_HDD,
7238 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007239 "%s: i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d",
7240 __func__, i, j, k,
7241 j + 1,
7242 StaParams.
7243 supported_channels[j +
7244 1]);
7245 j += 1;
7246 }
7247 }
7248 num_unique_channels = j + 1;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307249 QDF_TRACE(QDF_MODULE_ID_HDD,
7250 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007251 "%s: Unique Channel List", __func__);
7252 for (i = 0; i < num_unique_channels; i++) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307253 QDF_TRACE(QDF_MODULE_ID_HDD,
7254 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007255 "%s: StaParams.supported_channels[%d]: %d,",
7256 __func__, i,
7257 StaParams.
7258 supported_channels[i]);
7259 }
7260 if (MAX_CHANNEL < num_unique_channels)
7261 num_unique_channels = MAX_CHANNEL;
7262 StaParams.supported_channels_len =
7263 num_unique_channels;
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307264 QDF_TRACE(QDF_MODULE_ID_HDD,
7265 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007266 "%s: After removing duplcates StaParams.supported_channels_len: %d",
7267 __func__,
7268 StaParams.supported_channels_len);
7269 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307270 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007271 params->supported_oper_classes,
7272 params->supported_oper_classes_len);
7273 StaParams.supported_oper_classes_len =
7274 params->supported_oper_classes_len;
7275
7276 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307277 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007278 params->ext_capab,
7279 sizeof(StaParams.extn_capability));
7280
7281 if (NULL != params->ht_capa) {
7282 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307283 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007284 sizeof(tSirHTCap));
7285 }
7286
7287 StaParams.supported_rates_len =
7288 params->supported_rates_len;
7289
7290 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
7291 * The supported_rates array , for all the structures propogating till Add Sta
7292 * to the firmware has to be modified , if the supplicant (ieee80211) is
7293 * modified to send more rates.
7294 */
7295
7296 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
7297 */
7298 if (StaParams.supported_rates_len >
7299 SIR_MAC_MAX_SUPP_RATES)
7300 StaParams.supported_rates_len =
7301 SIR_MAC_MAX_SUPP_RATES;
7302
7303 if (0 != StaParams.supported_rates_len) {
7304 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307305 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007306 params->supported_rates,
7307 StaParams.supported_rates_len);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307308 QDF_TRACE(QDF_MODULE_ID_HDD,
7309 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007310 "Supported Rates with Length %d",
7311 StaParams.supported_rates_len);
7312 for (i = 0; i < StaParams.supported_rates_len;
7313 i++)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307314 QDF_TRACE(QDF_MODULE_ID_HDD,
7315 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007316 "[%d]: %0x", i,
7317 StaParams.supported_rates[i]);
7318 }
7319
7320 if (NULL != params->vht_capa) {
7321 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307322 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007323 params->vht_capa,
7324 sizeof(tSirVHTCap));
7325 }
7326
7327 if (0 != params->ext_capab_len) {
7328 /*Define A Macro : TODO Sunil */
7329 if ((1 << 4) & StaParams.extn_capability[3]) {
7330 isBufSta = 1;
7331 }
7332 /* TDLS Channel Switching Support */
7333 if ((1 << 6) & StaParams.extn_capability[3]) {
7334 isOffChannelSupported = 1;
7335 }
7336 }
7337
7338 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
7339 &StaParams,
7340 isBufSta,
7341 isOffChannelSupported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307342 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307343 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007344 FL
7345 ("wlan_hdd_tdls_set_peer_caps failed!"));
7346 return -EINVAL;
7347 }
7348
7349 status =
7350 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
7351 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307352 if (QDF_STATUS_SUCCESS != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307353 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007354 FL("wlan_hdd_tdls_add_station failed!"));
7355 return -EINVAL;
7356 }
7357 }
7358#endif
7359 }
7360 EXIT();
7361 return ret;
7362}
7363
7364/**
7365 * wlan_hdd_change_station() - cfg80211 change station handler function
7366 * @wiphy: Pointer to the wiphy structure
7367 * @dev: Pointer to the net device.
7368 * @mac: bssid
7369 * @params: Pointer to station parameters
7370 *
7371 * This is the cfg80211 change station handler function which invokes
7372 * the internal function @__wlan_hdd_change_station with
7373 * SSR protection.
7374 *
7375 * Return: 0 for success, error number on failure.
7376 */
7377#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
7378static int wlan_hdd_change_station(struct wiphy *wiphy,
7379 struct net_device *dev,
7380 const u8 *mac,
7381 struct station_parameters *params)
7382#else
7383static int wlan_hdd_change_station(struct wiphy *wiphy,
7384 struct net_device *dev,
7385 u8 *mac,
7386 struct station_parameters *params)
7387#endif
7388{
7389 int ret;
7390
7391 cds_ssr_protect(__func__);
7392 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
7393 cds_ssr_unprotect(__func__);
7394
7395 return ret;
7396}
7397
7398/*
7399 * FUNCTION: __wlan_hdd_cfg80211_add_key
7400 * This function is used to initialize the key information
7401 */
7402static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
7403 struct net_device *ndev,
7404 u8 key_index, bool pairwise,
7405 const u8 *mac_addr,
7406 struct key_params *params)
7407{
7408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7409 tCsrRoamSetKey setKey;
7410 int status;
7411 uint32_t roamId = 0xFF;
7412#ifndef WLAN_FEATURE_MBSSID
7413 v_CONTEXT_t p_cds_context = (WLAN_HDD_GET_CTX(pAdapter))->pcds_context;
7414#endif
7415 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307416 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007417 hdd_context_t *pHddCtx;
7418 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7419
7420 ENTER();
7421
Anurag Chouhan6d760662016-02-20 16:05:43 +05307422 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007423 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7424 return -EINVAL;
7425 }
7426
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307427 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007428 TRACE_CODE_HDD_CFG80211_ADD_KEY,
7429 pAdapter->sessionId, params->key_len));
7430 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7431 status = wlan_hdd_validate_context(pHddCtx);
7432
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307433 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007434 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007435
7436 hddLog(LOG1, FL("Device_mode %s(%d)"),
7437 hdd_device_mode_to_string(pAdapter->device_mode),
7438 pAdapter->device_mode);
7439
7440 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307441 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007442 __func__, key_index);
7443
7444 return -EINVAL;
7445 }
7446
7447 if (CSR_MAX_KEY_LEN < params->key_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307448 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: Invalid key length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007449 __func__, params->key_len);
7450
7451 return -EINVAL;
7452 }
7453
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307454 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007455 "%s: called with key index = %d & key length %d",
7456 __func__, key_index, params->key_len);
7457
7458 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307459 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007460 setKey.keyId = key_index;
7461 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307462 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007463
7464 switch (params->cipher) {
7465 case WLAN_CIPHER_SUITE_WEP40:
7466 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
7467 break;
7468
7469 case WLAN_CIPHER_SUITE_WEP104:
7470 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
7471 break;
7472
7473 case WLAN_CIPHER_SUITE_TKIP:
7474 {
7475 u8 *pKey = &setKey.Key[0];
7476 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
7477
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307478 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007479
7480 /*Supplicant sends the 32bytes key in this order
7481
7482 |--------------|----------|----------|
7483 | Tk1 |TX-MIC | RX Mic |
7484 |||--------------|----------|----------|
7485 <---16bytes---><--8bytes--><--8bytes-->
7486
7487 */
7488 /*Sme expects the 32 bytes key to be in the below order
7489
7490 |--------------|----------|----------|
7491 | Tk1 |RX-MIC | TX Mic |
7492 |||--------------|----------|----------|
7493 <---16bytes---><--8bytes--><--8bytes-->
7494 */
7495 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307496 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007497
7498 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307499 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007500
7501 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307502 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007503
7504 break;
7505 }
7506
7507 case WLAN_CIPHER_SUITE_CCMP:
7508 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
7509 break;
7510
7511#ifdef FEATURE_WLAN_WAPI
7512 case WLAN_CIPHER_SUITE_SMS4:
7513 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307514 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007515 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
7516 mac_addr, params->key,
7517 params->key_len);
7518 return 0;
7519 }
7520#endif
7521
7522#ifdef FEATURE_WLAN_ESE
7523 case WLAN_CIPHER_SUITE_KRK:
7524 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
7525 break;
7526#ifdef WLAN_FEATURE_ROAM_OFFLOAD
7527 case WLAN_CIPHER_SUITE_BTK:
7528 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
7529 break;
7530#endif
7531#endif
7532
7533#ifdef WLAN_FEATURE_11W
7534 case WLAN_CIPHER_SUITE_AES_CMAC:
7535 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
7536 break;
7537#endif
7538
7539 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307540 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007541 __func__, params->cipher);
7542 return -EOPNOTSUPP;
7543 }
7544
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307545 hddLog(QDF_TRACE_LEVEL_INFO_MED, "%s: encryption type %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007546 __func__, setKey.encType);
7547
7548 if (!pairwise) {
7549 /* set group key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307550 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007551 "%s- %d: setting Broadcast key", __func__, __LINE__);
7552 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05307553 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007554 } else {
7555 /* set pairwise key */
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307556 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007557 "%s- %d: setting pairwise key", __func__, __LINE__);
7558 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307559 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007560 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007561 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007562 /* if a key is already installed, block all subsequent ones */
7563 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307564 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007565 "%s: IBSS key installed already", __func__);
7566 return 0;
7567 }
7568
7569 setKey.keyDirection = eSIR_TX_RX;
7570 /*Set the group key */
7571 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7572 pAdapter->sessionId, &setKey, &roamId);
7573
7574 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307575 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007576 "%s: sme_roam_set_key failed, returned %d",
7577 __func__, status);
7578 return -EINVAL;
7579 }
7580 /*Save the keys here and call sme_roam_set_key for setting
7581 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307582 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007583 &setKey, sizeof(tCsrRoamSetKey));
7584
7585 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
7586 return status;
7587 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007588 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
7589 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007590 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7591 if (pHostapdState->bssState == BSS_START) {
7592#ifdef WLAN_FEATURE_MBSSID
7593 status =
7594 wlansap_set_key_sta(WLAN_HDD_GET_SAP_CTX_PTR
7595 (pAdapter), &setKey);
7596#else
7597 status = wlansap_set_key_sta(p_cds_context, &setKey);
7598#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307599 if (status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307600 QDF_TRACE(QDF_MODULE_ID_HDD,
7601 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007602 "[%4d] wlansap_set_key_sta returned ERROR status= %d",
7603 __LINE__, status);
7604 }
7605 }
7606
7607 /* Save the key in ap ctx for use on START_BASS and restart */
7608 if (pairwise ||
7609 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
7610 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307611 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007612 sizeof(tCsrRoamSetKey));
7613 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307614 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007615 sizeof(tCsrRoamSetKey));
7616
Krunal Sonib4326f22016-03-10 13:05:51 -08007617 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
7618 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007619 hdd_wext_state_t *pWextState =
7620 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7621 hdd_station_ctx_t *pHddStaCtx =
7622 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7623
7624 if (!pairwise) {
7625 /* set group key */
7626 if (pHddStaCtx->roam_info.deferKeyComplete) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307627 QDF_TRACE(QDF_MODULE_ID_HDD,
7628 QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007629 "%s- %d: Perform Set key Complete",
7630 __func__, __LINE__);
7631 hdd_perform_roam_set_key_complete(pAdapter);
7632 }
7633 }
7634
7635 pWextState->roamProfile.Keys.KeyLength[key_index] =
7636 (u8) params->key_len;
7637
7638 pWextState->roamProfile.Keys.defaultIndex = key_index;
7639
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307640 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007641 KeyMaterial[key_index][0], params->key,
7642 params->key_len);
7643
7644 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
7645
7646 hddLog(LOG2,
7647 FL("Set key for peerMac "MAC_ADDRESS_STR" direction %d"),
7648 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
7649 setKey.keyDirection);
7650
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007651 /* The supplicant may attempt to set the PTK once pre-authentication
7652 is done. Save the key in the UMAC and include it in the ADD BSS
7653 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307654 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007655 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307656 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307657 hddLog(QDF_TRACE_LEVEL_INFO_MED,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007658 "%s: Update PreAuth Key success", __func__);
7659 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05307660 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307661 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007662 "%s: Update PreAuth Key failed", __func__);
7663 return -EINVAL;
7664 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007665
7666 /* issue set key request to SME */
7667 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7668 pAdapter->sessionId, &setKey, &roamId);
7669
7670 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307671 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007672 "%s: sme_roam_set_key failed, returned %d",
7673 __func__, status);
7674 pHddStaCtx->roam_info.roamingState =
7675 HDD_ROAM_STATE_NONE;
7676 return -EINVAL;
7677 }
7678
7679 /* in case of IBSS as there was no information available about WEP keys during
7680 * IBSS join, group key intialized with NULL key, so re-initialize group key
7681 * with correct value*/
7682 if ((eCSR_BSS_TYPE_START_IBSS ==
7683 pWextState->roamProfile.BSSType)
7684 &&
7685 !((IW_AUTH_KEY_MGMT_802_1X ==
7686 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
7687 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
7688 pHddStaCtx->conn_info.authType)
7689 )
7690 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
7691 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
7692 )
7693 ) {
7694 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05307695 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007696
7697 hddLog(LOG2,
7698 FL("Set key peerMac "MAC_ADDRESS_STR" direction %d"),
7699 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
7700 setKey.keyDirection);
7701
7702 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7703 pAdapter->sessionId, &setKey,
7704 &roamId);
7705
7706 if (0 != status) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307707 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007708 "%s: sme_roam_set_key failed for group key (IBSS), returned %d",
7709 __func__, status);
7710 pHddStaCtx->roam_info.roamingState =
7711 HDD_ROAM_STATE_NONE;
7712 return -EINVAL;
7713 }
7714 }
7715 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307716 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007717 return 0;
7718}
7719
7720static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
7721 struct net_device *ndev,
7722 u8 key_index, bool pairwise,
7723 const u8 *mac_addr,
7724 struct key_params *params)
7725{
7726 int ret;
7727 cds_ssr_protect(__func__);
7728 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
7729 mac_addr, params);
7730 cds_ssr_unprotect(__func__);
7731
7732 return ret;
7733}
7734
7735/*
7736 * FUNCTION: __wlan_hdd_cfg80211_get_key
7737 * This function is used to get the key information
7738 */
7739static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7740 struct net_device *ndev,
7741 u8 key_index, bool pairwise,
7742 const u8 *mac_addr, void *cookie,
7743 void (*callback)(void *cookie,
7744 struct key_params *)
7745 )
7746{
7747 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7748 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7749 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
7750 struct key_params params;
7751
7752 ENTER();
7753
Anurag Chouhan6d760662016-02-20 16:05:43 +05307754 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007755 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7756 return -EINVAL;
7757 }
7758
7759 hddLog(LOG1, FL("Device_mode %s(%d)"),
7760 hdd_device_mode_to_string(pAdapter->device_mode),
7761 pAdapter->device_mode);
7762
7763 memset(&params, 0, sizeof(params));
7764
7765 if (CSR_MAX_NUM_KEY <= key_index) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307766 hddLog(QDF_TRACE_LEVEL_ERROR, FL("invalid key index %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007767 key_index);
7768 return -EINVAL;
7769 }
7770
7771 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
7772 case eCSR_ENCRYPT_TYPE_NONE:
7773 params.cipher = IW_AUTH_CIPHER_NONE;
7774 break;
7775
7776 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
7777 case eCSR_ENCRYPT_TYPE_WEP40:
7778 params.cipher = WLAN_CIPHER_SUITE_WEP40;
7779 break;
7780
7781 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
7782 case eCSR_ENCRYPT_TYPE_WEP104:
7783 params.cipher = WLAN_CIPHER_SUITE_WEP104;
7784 break;
7785
7786 case eCSR_ENCRYPT_TYPE_TKIP:
7787 params.cipher = WLAN_CIPHER_SUITE_TKIP;
7788 break;
7789
7790 case eCSR_ENCRYPT_TYPE_AES:
7791 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
7792 break;
7793
7794 default:
7795 params.cipher = IW_AUTH_CIPHER_NONE;
7796 break;
7797 }
7798
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307799 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007800 TRACE_CODE_HDD_CFG80211_GET_KEY,
7801 pAdapter->sessionId, params.cipher));
7802
7803 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
7804 params.seq_len = 0;
7805 params.seq = NULL;
7806 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
7807 callback(cookie, &params);
7808
7809 EXIT();
7810 return 0;
7811}
7812
7813static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
7814 struct net_device *ndev,
7815 u8 key_index, bool pairwise,
7816 const u8 *mac_addr, void *cookie,
7817 void (*callback)(void *cookie,
7818 struct key_params *)
7819 )
7820{
7821 int ret;
7822
7823 cds_ssr_protect(__func__);
7824 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
7825 mac_addr, cookie, callback);
7826 cds_ssr_unprotect(__func__);
7827
7828 return ret;
7829}
7830
7831/**
7832 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
7833 * @wiphy: wiphy interface context
7834 * @ndev: pointer to net device
7835 * @key_index: Key index used in 802.11 frames
7836 * @unicast: true if it is unicast key
7837 * @multicast: true if it is multicast key
7838 *
7839 * This function is required for cfg80211_ops API.
7840 * It is used to delete the key information
7841 * Underlying hardware implementation does not have API to delete the
7842 * encryption key. It is automatically deleted when the peer is
7843 * removed. Hence this function currently does nothing.
7844 * Future implementation may interprete delete key operation to
7845 * replacing the key with a random junk value, effectively making it
7846 * useless.
7847 *
7848 * Return: status code, always 0.
7849 */
7850
7851static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7852 struct net_device *ndev,
7853 u8 key_index,
7854 bool pairwise, const u8 *mac_addr)
7855{
7856 EXIT();
7857 return 0;
7858}
7859
7860/**
7861 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
7862 * @wiphy: Pointer to wiphy structure.
7863 * @dev: Pointer to net_device structure.
7864 * @key_index: key index
7865 * @pairwise: pairwise
7866 * @mac_addr: mac address
7867 *
7868 * This is the cfg80211 delete key handler function which invokes
7869 * the internal function @__wlan_hdd_cfg80211_del_key with
7870 * SSR protection.
7871 *
7872 * Return: 0 for success, error number on failure.
7873 */
7874static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
7875 struct net_device *dev,
7876 u8 key_index,
7877 bool pairwise, const u8 *mac_addr)
7878{
7879 int ret;
7880
7881 cds_ssr_protect(__func__);
7882 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
7883 pairwise, mac_addr);
7884 cds_ssr_unprotect(__func__);
7885
7886 return ret;
7887}
7888
7889/*
7890 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
7891 * This function is used to set the default tx key index
7892 */
7893static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
7894 struct net_device *ndev,
7895 u8 key_index,
7896 bool unicast, bool multicast)
7897{
7898 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7899 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7900 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7901 hdd_context_t *pHddCtx;
7902 int status;
7903
7904 ENTER();
7905
Anurag Chouhan6d760662016-02-20 16:05:43 +05307906 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007907 hddLog(LOGE, FL("Command not allowed in FTM mode"));
7908 return -EINVAL;
7909 }
7910
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05307911 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007912 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
7913 pAdapter->sessionId, key_index));
7914
7915 hddLog(LOG1, FL("Device_mode %s(%d) key_index = %d"),
7916 hdd_device_mode_to_string(pAdapter->device_mode),
7917 pAdapter->device_mode, key_index);
7918
7919 if (CSR_MAX_NUM_KEY <= key_index) {
7920 hddLog(LOGE, FL("Invalid key index %d"), key_index);
7921 return -EINVAL;
7922 }
7923
7924 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7925 status = wlan_hdd_validate_context(pHddCtx);
7926
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05307927 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007928 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007929
Krunal Sonib4326f22016-03-10 13:05:51 -08007930 if ((pAdapter->device_mode == QDF_STA_MODE) ||
7931 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007932 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7933 pHddStaCtx->conn_info.ucEncryptionType) &&
7934 (eCSR_ENCRYPT_TYPE_AES !=
7935 pHddStaCtx->conn_info.ucEncryptionType)) {
7936 /* If default key index is not same as previous one,
7937 * then update the default key index */
7938
7939 tCsrRoamSetKey setKey;
7940 uint32_t roamId = 0xFF;
7941 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
7942
7943 hddLog(LOG2, FL("Default tx key index %d"), key_index);
7944
7945 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307946 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007947 setKey.keyId = key_index;
7948 setKey.keyLength = Keys->KeyLength[key_index];
7949
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307950 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007951 &Keys->KeyMaterial[key_index][0],
7952 Keys->KeyLength[key_index]);
7953
7954 setKey.keyDirection = eSIR_TX_RX;
7955
Anurag Chouhanc5548422016-02-24 18:33:27 +05307956 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007957 &pHddStaCtx->conn_info.bssId);
7958
7959 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
7960 pWextState->roamProfile.EncryptionType.
7961 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
7962 /* In the case of dynamic wep supplicant hardcodes DWEP type
7963 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
7964 * WEP-40 encryption. In this canse the key length is 5 but the
7965 * encryption type is 104 hence checking the key langht(5) and
7966 * encryption type(104) and switching encryption type to 40*/
7967 pWextState->roamProfile.EncryptionType.
7968 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7969 pWextState->roamProfile.mcEncryptionType.
7970 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
7971 }
7972
7973 setKey.encType =
7974 pWextState->roamProfile.EncryptionType.
7975 encryptionType[0];
7976
7977 /* Issue set key request */
7978 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
7979 pAdapter->sessionId, &setKey,
7980 &roamId);
7981
7982 if (0 != status) {
7983 hddLog(LOGE,
7984 FL("sme_roam_set_key failed, returned %d"),
7985 status);
7986 return -EINVAL;
7987 }
7988 }
Krunal Sonib4326f22016-03-10 13:05:51 -08007989 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007990 /* In SoftAp mode setting key direction for default mode */
7991 if ((eCSR_ENCRYPT_TYPE_TKIP !=
7992 pWextState->roamProfile.EncryptionType.encryptionType[0])
7993 && (eCSR_ENCRYPT_TYPE_AES !=
7994 pWextState->roamProfile.EncryptionType.
7995 encryptionType[0])) {
7996 /* Saving key direction for default key index to TX default */
7997 hdd_ap_ctx_t *pAPCtx =
7998 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7999 pAPCtx->wepKey[key_index].keyDirection =
8000 eSIR_TX_DEFAULT;
8001 }
8002 }
8003
8004 EXIT();
8005 return status;
8006}
8007
8008static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
8009 struct net_device *ndev,
8010 u8 key_index,
8011 bool unicast, bool multicast)
8012{
8013 int ret;
8014 cds_ssr_protect(__func__);
8015 ret =
8016 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
8017 multicast);
8018 cds_ssr_unprotect(__func__);
8019
8020 return ret;
8021}
8022
8023/**
8024 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
8025 * @pAdapter: Pointer to adapter
8026 * @pRoamInfo: Pointer to roam info
8027 *
8028 * Return: struct cfg80211_bss pointer
8029 */
8030struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
8031 tCsrRoamInfo *pRoamInfo)
8032{
8033 struct net_device *dev = pAdapter->dev;
8034 struct wireless_dev *wdev = dev->ieee80211_ptr;
8035 struct wiphy *wiphy = wdev->wiphy;
8036 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
8037 int chan_no;
8038 unsigned int freq;
8039 struct ieee80211_channel *chan;
8040 struct cfg80211_bss *bss = NULL;
8041
8042 ENTER();
8043
8044 if (NULL == pBssDesc) {
8045 hddLog(LOGE, FL("pBssDesc is NULL"));
8046 return bss;
8047 }
8048
8049 if (NULL == pRoamInfo->pProfile) {
8050 hddLog(LOGE, FL("Roam profile is NULL"));
8051 return bss;
8052 }
8053
8054 chan_no = pBssDesc->channelId;
8055
8056 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
8057 freq =
8058 ieee80211_channel_to_frequency(chan_no,
8059 IEEE80211_BAND_2GHZ);
8060 } else {
8061 freq =
8062 ieee80211_channel_to_frequency(chan_no,
8063 IEEE80211_BAND_5GHZ);
8064 }
8065
8066 chan = __ieee80211_get_channel(wiphy, freq);
8067
8068 if (!chan) {
8069 hddLog(LOGE, FL("chan pointer is NULL"));
8070 return NULL;
8071 }
8072
8073 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
8074 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
8075 ssId[0],
8076 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
Ryan Hsu535d16a2016-01-18 16:45:12 -08008077#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008078 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
Ryan Hsu535d16a2016-01-18 16:45:12 -08008079#else
8080 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
8081#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008082 if (bss == NULL) {
8083 hddLog(LOGE, FL("BSS not present"));
8084 } else {
8085 hddLog(LOG1, FL("cfg80211_unlink_bss called for BSSID "
8086 MAC_ADDRESS_STR),
8087 MAC_ADDR_ARRAY(pBssDesc->bssId));
8088 cfg80211_unlink_bss(wiphy, bss);
8089 }
8090 return bss;
8091}
8092
8093/**
8094 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
8095 * @pAdapter: Pointer to adapter
8096 * @bss_desc: Pointer to bss descriptor
8097 *
8098 * This function is used to inform the BSS details to nl80211 interface.
8099 *
8100 * Return: struct cfg80211_bss pointer
8101 */
8102static struct cfg80211_bss *
8103wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
8104 tSirBssDescription *bss_desc)
8105{
8106 /*
8107 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
8108 * already exists in bss data base of cfg80211 for that particular BSS
8109 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
8110 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
8111 * As of now there is no possibility to get the mgmt(probe response)
8112 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
8113 * and passing to cfg80211_inform_bss_frame.
8114 */
8115 struct net_device *dev = pAdapter->dev;
8116 struct wireless_dev *wdev = dev->ieee80211_ptr;
8117 struct wiphy *wiphy = wdev->wiphy;
8118 int chan_no = bss_desc->channelId;
8119#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
8120 qcom_ie_age *qie_age = NULL;
8121 int ie_length =
8122 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
8123#else
8124 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
8125#endif
8126 const char *ie =
8127 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
8128 unsigned int freq;
8129 struct ieee80211_channel *chan;
8130 struct ieee80211_mgmt *mgmt = NULL;
8131 struct cfg80211_bss *bss_status = NULL;
8132 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
8133 int rssi = 0;
8134 hdd_context_t *pHddCtx;
8135 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008136 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07008137 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008138
8139 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8140 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308141 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008142 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008143
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07008144 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008145 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
8146 if (!mgmt) {
8147 hddLog(LOGE, FL("memory allocation failed"));
8148 return NULL;
8149 }
8150
8151 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
8152
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008153 /* Android does not want the timestamp from the frame.
8154 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -07008155 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008156 mgmt->u.probe_resp.timestamp =
8157 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008158
8159 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
8160 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
8161
8162#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
8163 /* GPS Requirement: need age ie per entry. Using vendor specific. */
8164 /* Assuming this is the last IE, copy at the end */
8165 ie_length -= sizeof(qcom_ie_age);
8166 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
8167 qie_age->element_id = QCOM_VENDOR_IE_ID;
8168 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
8169 qie_age->oui_1 = QCOM_OUI1;
8170 qie_age->oui_2 = QCOM_OUI2;
8171 qie_age->oui_3 = QCOM_OUI3;
8172 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
8173 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +05308174 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008175 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -07008176 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
8177 sizeof(qie_age->beacon_tsf));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178#endif
8179
8180 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
8181 if (bss_desc->fProbeRsp) {
8182 mgmt->frame_control |=
8183 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
8184 } else {
8185 mgmt->frame_control |=
8186 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
8187 }
8188
8189 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
8190 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
8191 freq =
8192 ieee80211_channel_to_frequency(chan_no,
8193 IEEE80211_BAND_2GHZ);
8194 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
8195 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
8196 freq =
8197 ieee80211_channel_to_frequency(chan_no,
8198 IEEE80211_BAND_5GHZ);
8199 } else {
8200 hddLog(LOGE, FL("Invalid chan_no %d"), chan_no);
8201 kfree(mgmt);
8202 return NULL;
8203 }
8204
8205 chan = __ieee80211_get_channel(wiphy, freq);
8206 /* When the band is changed on the fly using the GUI, three things are done
8207 * 1. scan abort
8208 * 2. flush scan results from cache
8209 * 3. update the band with the new band user specified (refer to the
8210 * hdd_set_band_helper function) as part of the scan abort, message will be
8211 * queued to PE and we proceed with flushing and changinh the band.
8212 * PE will stop the scanning further and report back the results what ever
8213 * it had till now by calling the call back function.
8214 * if the time between update band and scandone call back is sufficient
8215 * enough the band change reflects in SME, SME validates the channels
8216 * and discards the channels correponding to previous band and calls back
8217 * with zero bss results. but if the time between band update and scan done
8218 * callback is very small then band change will not reflect in SME and SME
8219 * reports to HDD all the channels correponding to previous band.this is due
8220 * to race condition.but those channels are invalid to the new band and so
8221 * this function __ieee80211_get_channel will return NULL.Each time we
8222 * report scan result with this pointer null warning kernel trace is printed.
8223 * if the scan results contain large number of APs continuosly kernel
8224 * warning trace is printed and it will lead to apps watch dog bark.
8225 * So drop the bss and continue to next bss.
8226 */
8227 if (chan == NULL) {
8228 hddLog(LOGE, FL("chan pointer is NULL"));
8229 kfree(mgmt);
8230 return NULL;
8231 }
8232
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07008233 /* Based on .ini configuration, raw rssi can be reported for bss.
8234 * Raw rssi is typically used for estimating power.
8235 */
8236
8237 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
8238 bss_desc->rssi;
8239
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008240 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +05308241 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008242
Sandeep Puligilla394da5d2016-05-06 01:26:29 -07008243 hddLog(LOG1, FL("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008244 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -07008245 (int)(rssi / 100),
8246 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008247
8248 bss_status =
8249 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
8250 GFP_KERNEL);
8251 kfree(mgmt);
8252 return bss_status;
8253}
8254
8255/**
8256 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
8257 * @pAdapter: Pointer to adapter
8258 * @pRoamInfo: Pointer to roam info
8259 *
8260 * This function is used to update the BSS data base of CFG8011
8261 *
8262 * Return: struct cfg80211_bss pointer
8263 */
8264struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
8265 tCsrRoamInfo *pRoamInfo)
8266{
8267 tCsrRoamConnectedProfile roamProfile;
8268 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8269 struct cfg80211_bss *bss = NULL;
8270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008271 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
8272 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
8273
8274 if (NULL != roamProfile.pBssDesc) {
8275 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
8276 roamProfile.pBssDesc);
8277
8278 if (NULL == bss)
8279 hddLog(LOG1,
8280 FL("wlan_hdd_cfg80211_inform_bss_frame returned NULL"));
8281
Naveen Rawatdf0a7e72016-01-06 18:35:53 -08008282 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008283 } else {
8284 hddLog(LOGE, FL("roamProfile.pBssDesc is NULL"));
8285 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008286 return bss;
8287}
8288/**
8289 * wlan_hdd_cfg80211_update_bss() - update bss
8290 * @wiphy: Pointer to wiphy
8291 * @pAdapter: Pointer to adapter
8292 * @scan_time: scan request timestamp
8293 *
8294 * Return: zero if success, non-zero otherwise
8295 */
8296int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
8297 hdd_adapter_t *pAdapter,
8298 uint32_t scan_time)
8299{
8300 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8301 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308302 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008303 tScanResultHandle pResult;
8304 struct cfg80211_bss *bss_status = NULL;
8305 hdd_context_t *pHddCtx;
8306 int ret;
8307
8308 ENTER();
8309
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308310 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008311 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
8312 NO_SESSION, pAdapter->sessionId));
8313
8314 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8315 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308316 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008317 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008318
8319 /* start getting scan results and populate cgf80211 BSS database */
8320 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
8321
8322 /* no scan results */
8323 if (NULL == pResult) {
8324 hddLog(LOGE, FL("No scan result Status %d"), status);
8325 return status;
8326 }
8327
8328 pScanResult = sme_scan_result_get_first(hHal, pResult);
8329
8330 while (pScanResult) {
8331 /*
8332 * - cfg80211_inform_bss() is not updating ie field of bss
8333 * entry if entry already exists in bss data base of cfg80211
8334 * for that particular BSS ID. Using cfg80211_inform_bss_frame
8335 * to update thebss entry instead of cfg80211_inform_bss,
8336 * But this call expects mgmt packet as input. As of now
8337 * there is no possibility to get the mgmt(probe response)
8338 * frame from PE, converting bss_desc to
8339 * ieee80211_mgmt(probe response) and passing to c
8340 * fg80211_inform_bss_frame.
8341 * - Update BSS only if beacon timestamp is later than
8342 * scan request timestamp.
8343 */
8344 if ((scan_time == 0) ||
8345 (scan_time <
8346 pScanResult->BssDescriptor.nReceivedTime)) {
8347 bss_status =
8348 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
8349 &pScanResult->BssDescriptor);
8350
8351 if (NULL == bss_status) {
8352 hdd_info("NULL returned by cfg80211_inform_bss_frame");
8353 } else {
8354 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008355 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008356 bss_status);
8357 }
8358 } else {
8359 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
8360 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
8361 }
8362 pScanResult = sme_scan_result_get_next(hHal, pResult);
8363 }
8364
8365 sme_scan_result_purge(hHal, pResult);
8366 /*
8367 * For SAP mode, scan is invoked by hostapd during SAP start
8368 * if hostapd is restarted, we need to flush previous scan
8369 * result so that it will reflect environment change
8370 */
Krunal Sonib4326f22016-03-10 13:05:51 -08008371 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008372#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
8373 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
8374#endif
8375 )
8376 sme_scan_flush_result(hHal);
8377
8378 EXIT();
8379 return 0;
8380}
8381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008382/**
8383 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
8384 * @pAdapter: Pointer to adapter
8385 * @pRoamInfo: Pointer to roam info
8386 * @index: Index
8387 * @preauth: Preauth flag
8388 *
8389 * This function is used to notify the supplicant of a new PMKSA candidate.
8390 *
8391 * Return: 0 for success, non-zero for failure
8392 */
8393int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
8394 tCsrRoamInfo *pRoamInfo,
8395 int index, bool preauth)
8396{
8397#ifdef FEATURE_WLAN_OKC
8398 struct net_device *dev = pAdapter->dev;
8399 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
8400
8401 ENTER();
8402 hddLog(LOG1, FL("is going to notify supplicant of:"));
8403
8404 if (NULL == pRoamInfo) {
8405 hddLog(LOGP, FL("pRoamInfo is NULL"));
8406 return -EINVAL;
8407 }
8408
8409 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
8410 hddLog(LOG1, MAC_ADDRESS_STR,
8411 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
8412 cfg80211_pmksa_candidate_notify(dev, index,
8413 pRoamInfo->bssid.bytes,
8414 preauth, GFP_KERNEL);
8415 }
8416#endif /* FEATURE_WLAN_OKC */
8417 return 0;
8418}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008419
8420#ifdef FEATURE_WLAN_LFR_METRICS
8421/**
8422 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
8423 * @pAdapter: Pointer to adapter
8424 * @pRoamInfo: Pointer to roam info
8425 *
8426 * 802.11r/LFR metrics reporting function to report preauth initiation
8427 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308428 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008429 */
8430#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308431QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008432 tCsrRoamInfo *pRoamInfo)
8433{
8434 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8435 union iwreq_data wrqu;
8436
8437 ENTER();
8438
8439 if (NULL == pAdapter) {
8440 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308441 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008442 }
8443
8444 /* create the event */
8445 memset(&wrqu, 0, sizeof(wrqu));
8446 memset(metrics_notification, 0, sizeof(metrics_notification));
8447
8448 wrqu.data.pointer = metrics_notification;
8449 wrqu.data.length = scnprintf(metrics_notification,
8450 sizeof(metrics_notification),
8451 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
8452 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8453
8454 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
8455 metrics_notification);
8456
8457 EXIT();
8458
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308459 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008460}
8461
8462/**
8463 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
8464 * @pAdapter: Pointer to adapter
8465 * @pRoamInfo: Pointer to roam info
8466 * @preauth_status: Preauth status
8467 *
8468 * 802.11r/LFR metrics reporting function to report handover initiation
8469 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308470 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008471 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308472QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008473wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
8474 tCsrRoamInfo *pRoamInfo,
8475 bool preauth_status)
8476{
8477 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8478 union iwreq_data wrqu;
8479
8480 ENTER();
8481
8482 if (NULL == pAdapter) {
8483 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308484 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008485 }
8486
8487 /* create the event */
8488 memset(&wrqu, 0, sizeof(wrqu));
8489 memset(metrics_notification, 0, sizeof(metrics_notification));
8490
8491 scnprintf(metrics_notification, sizeof(metrics_notification),
8492 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
8493 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8494
8495 if (1 == preauth_status)
8496 strlcat(metrics_notification, " true",
8497 sizeof(metrics_notification));
8498 else
8499 strlcat(metrics_notification, " false",
8500 sizeof(metrics_notification));
8501
8502 wrqu.data.pointer = metrics_notification;
8503 wrqu.data.length = strlen(metrics_notification);
8504
8505 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
8506 metrics_notification);
8507
8508 EXIT();
8509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308510 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008511}
8512
8513/**
8514 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
8515 * @pAdapter: Pointer to adapter
8516 * @pRoamInfo: Pointer to roam info
8517 *
8518 * 802.11r/LFR metrics reporting function to report handover initiation
8519 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308520 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008521 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308522QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008523 tCsrRoamInfo *pRoamInfo)
8524{
8525 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
8526 union iwreq_data wrqu;
8527
8528 ENTER();
8529
8530 if (NULL == pAdapter) {
8531 hddLog(LOGE, FL("pAdapter is NULL!"));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308532 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008533 }
8534
8535 /* create the event */
8536 memset(&wrqu, 0, sizeof(wrqu));
8537 memset(metrics_notification, 0, sizeof(metrics_notification));
8538
8539 wrqu.data.pointer = metrics_notification;
8540 wrqu.data.length = scnprintf(metrics_notification,
8541 sizeof(metrics_notification),
8542 "QCOM: LFR_PREAUTH_HANDOVER "
8543 MAC_ADDRESS_STR,
8544 MAC_ADDR_ARRAY(pRoamInfo->bssid));
8545
8546 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
8547 metrics_notification);
8548
8549 EXIT();
8550
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308551 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008552}
8553#endif
8554
8555/**
8556 * hdd_select_cbmode() - select channel bonding mode
8557 * @pAdapter: Pointer to adapter
8558 * @operatingChannel: Operating channel
8559 *
8560 * Return: none
8561 */
8562void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel)
8563{
8564 uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
8565 eHddDot11Mode hddDot11Mode = iniDot11Mode;
Amar Singhale4f28ee2015-10-21 14:36:56 -07008566 struct ch_params_s ch_params;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008567 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008568 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008569 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008570
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008571 ch_params.ch_width =
8572 (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth;
8573
8574 hddLog(LOG1, FL("Channel Bonding Mode Selected is %u"), iniDot11Mode);
8575 switch (iniDot11Mode) {
8576 case eHDD_DOT11_MODE_AUTO:
8577 case eHDD_DOT11_MODE_11ac:
8578 case eHDD_DOT11_MODE_11ac_ONLY:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008579 if (sme_is_feature_supported_by_fw(DOT11AC))
8580 hddDot11Mode = eHDD_DOT11_MODE_11ac;
8581 else
8582 hddDot11Mode = eHDD_DOT11_MODE_11n;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008583 break;
8584 case eHDD_DOT11_MODE_11n:
8585 case eHDD_DOT11_MODE_11n_ONLY:
8586 hddDot11Mode = eHDD_DOT11_MODE_11n;
8587 break;
8588 default:
8589 hddDot11Mode = iniDot11Mode;
8590 break;
8591 }
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008592 /*
8593 * CDS api expects secondary channel for calculating
8594 * the channel params
8595 */
8596 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
8597 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
8598 if (operationChannel >= 1 && operationChannel <= 5)
8599 sec_ch = operationChannel + 4;
8600 else if (operationChannel >= 6 && operationChannel <= 13)
8601 sec_ch = operationChannel - 4;
8602 }
8603
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008604 /* This call decides required channel bonding mode */
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008605 cds_set_channel_params(operationChannel, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008606
8607 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
8608 ch_info->channel_width = ch_params.ch_width;
8609 ch_info->phy_mode = hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode);
8610 ch_info->channel = operationChannel;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008611 ch_info->cb_mode = ch_params.ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008612 hdd_info("ch_info width %d, phymode %d channel %d",
8613 ch_info->channel_width, ch_info->phy_mode,
8614 ch_info->channel);
8615 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008616}
8617
Rajeev Kumar249ea8d2016-04-15 16:57:46 -07008618/**
8619 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
8620 * @adapter: STA adapter
8621 * @roam_profile: STA roam profile
8622 *
8623 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
8624 *
8625 * Return: false if sta-sap conc is not allowed, else return true
8626 */
8627static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
8628 tCsrRoamProfile *roam_profile)
8629{
8630 hdd_context_t *hdd_ctx;
8631 hdd_adapter_t *ap_adapter;
8632 hdd_ap_ctx_t *hdd_ap_ctx;
8633 hdd_hostapd_state_t *hostapd_state;
8634 uint8_t channel = 0;
8635 QDF_STATUS status;
8636
8637 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8638 if (!hdd_ctx) {
8639 hdd_err("HDD context is NULL");
8640 return true;
8641 }
8642
8643 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
8644 /* probably no sap running, no handling required */
8645 if (ap_adapter == NULL)
8646 return true;
8647
8648 /*
8649 * sap is not in started state, so it is fine to go ahead with sta.
8650 * if sap is currently doing CAC then don't allow sta to go further.
8651 */
8652 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
8653 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
8654 return true;
8655
8656 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
8657 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
8658 return false;
8659 }
8660
8661 /*
8662 * log and return error, if we allow STA to go through, we don't
8663 * know what is going to happen better stop sta connection
8664 */
8665 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8666 if (NULL == hdd_ap_ctx) {
8667 hdd_err("AP context not found");
8668 return false;
8669 }
8670
8671 /* sap is on non-dfs channel, nothing to handle */
8672 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
8673 hdd_info("sap is on non-dfs channel, sta is allowed");
8674 return true;
8675 }
8676 /*
8677 * find out by looking in to scan cache where sta is going to
8678 * connect by passing its roam_profile. if channel is 0 or DFS then
8679 * better to call pcl and find out the best channel. if channel
8680 * is non-dfs then better move SAP to STA's channel to make
8681 * scc, so we have room for 3port MCC scenario
8682 */
8683 status = cds_get_channel_from_scan_result(adapter,
8684 roam_profile, &channel);
8685
8686 if ((QDF_STATUS_SUCCESS != status) || (0 == channel) ||
8687 CDS_IS_DFS_CH(channel))
8688 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
8689 true);
8690
8691 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
8692 qdf_event_reset(&hostapd_state->qdf_event);
8693 status = wlansap_set_channel_change_with_csa(
8694 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
8695 hdd_ap_ctx->sapConfig.ch_width_orig);
8696
8697 if (QDF_STATUS_SUCCESS != status) {
8698 hdd_err("Set channel with CSA IE failed, can't allow STA");
8699 return false;
8700 }
8701
8702 /*
8703 * wait here for SAP to finish the channel switch. When channel
8704 * switch happens, SAP sends few beacons with CSA_IE. After
8705 * successfully Transmission of those beacons, it will move its
8706 * state from started to disconnected and move to new channel.
8707 * once it moves to new channel, sap again moves its state
8708 * machine from disconnected to started and set this event.
8709 * wait for 10 secs to finish this.
8710 */
8711 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
8712 if (!QDF_IS_STATUS_SUCCESS(status)) {
8713 hdd_err("wait for qdf_event failed, STA not allowed!!");
8714 return false;
8715 }
8716
8717 return true;
8718}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008719
8720/*
8721 * FUNCTION: wlan_hdd_cfg80211_connect_start
8722 * wlan_hdd_cfg80211_connect_start() - start connection
8723 * @pAdapter: Pointer to adapter
8724 * @ssid: Pointer ot ssid
8725 * @ssid_len: Length of ssid
8726 * @bssid: Pointer to bssid
8727 * @operatingChannel: Operating channel
8728 *
8729 * This function is used to start the association process
8730 *
8731 * Return: 0 for success, non-zero for failure
8732 */
8733int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
8734 const u8 *ssid, size_t ssid_len,
8735 const u8 *bssid_hint, const u8 *bssid,
8736 u8 operatingChannel)
8737{
8738 int status = 0;
8739 hdd_wext_state_t *pWextState;
8740 hdd_context_t *pHddCtx;
8741 uint32_t roamId;
8742 tCsrRoamProfile *pRoamProfile;
8743 eCsrAuthType RSNAuthType;
8744 tSmeConfigParams *sme_config;
8745
8746 ENTER();
8747
8748 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8749 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8750
8751 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308752 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008753 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008754
8755 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
8756 hddLog(LOGE, FL("wrong SSID len"));
8757 return -EINVAL;
8758 }
8759
8760 pRoamProfile = &pWextState->roamProfile;
8761
8762 if (pRoamProfile) {
8763 hdd_station_ctx_t *pHddStaCtx;
8764 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8765
8766 if (HDD_WMM_USER_MODE_NO_QOS ==
8767 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
8768 /*QoS not enabled in cfg file */
8769 pRoamProfile->uapsd_mask = 0;
8770 } else {
8771 /*QoS enabled, update uapsd mask from cfg file */
8772 pRoamProfile->uapsd_mask =
8773 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
8774 }
8775
8776 pRoamProfile->SSIDs.numOfSSIDs = 1;
8777 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308778 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008779 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308780 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008781 ssid, ssid_len);
8782
8783 if (bssid) {
8784 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308785 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308786 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008787 /* Save BSSID in seperate variable as well, as RoamProfile
8788 BSSID is getting zeroed out in the association process. And in
8789 case of join failure we should send valid BSSID to supplicant
8790 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308791 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308792 bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008793 } else if (bssid_hint) {
8794 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308795 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308796 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008797 /* Save BSSID in separate variable as well, as
8798 RoamProfile BSSID is getting zeroed out in the
8799 association process. And in case of join failure
8800 we should send valid BSSID to supplicant
8801 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308802 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308803 bssid_hint, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008804 hddLog(LOGW, FL(" bssid_hint "MAC_ADDRESS_STR),
8805 MAC_ADDR_ARRAY(bssid_hint));
8806 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308807 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308808 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008809 }
8810
8811 hddLog(LOG1, FL("Connect to SSID: %.*s operating Channel: %u"),
8812 pRoamProfile->SSIDs.SSIDList->SSID.length,
8813 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
8814 operatingChannel);
8815
8816 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
8817 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
8818 /*set gen ie */
8819 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
8820 /*set auth */
8821 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
8822 }
8823#ifdef FEATURE_WLAN_WAPI
8824 if (pAdapter->wapi_info.nWapiMode) {
8825 hddLog(LOG1,
8826 FL("Setting WAPI AUTH Type and Encryption Mode values"));
8827 switch (pAdapter->wapi_info.wapiAuthMode) {
8828 case WAPI_AUTH_MODE_PSK:
8829 {
8830 hddLog(LOG1,
8831 FL("WAPI AUTH TYPE: PSK: %d"),
8832 pAdapter->wapi_info.wapiAuthMode);
8833 pRoamProfile->AuthType.authType[0] =
8834 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
8835 break;
8836 }
8837 case WAPI_AUTH_MODE_CERT:
8838 {
8839 hddLog(LOG1,
8840 FL("WAPI AUTH TYPE: CERT: %d"),
8841 pAdapter->wapi_info.wapiAuthMode);
8842 pRoamProfile->AuthType.authType[0] =
8843 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
8844 break;
8845 }
8846 } /* End of switch */
8847 if (pAdapter->wapi_info.wapiAuthMode ==
8848 WAPI_AUTH_MODE_PSK
8849 || pAdapter->wapi_info.wapiAuthMode ==
8850 WAPI_AUTH_MODE_CERT) {
8851 hddLog(LOG1,
8852 FL("WAPI PAIRWISE/GROUP ENCRYPTION: WPI"));
8853 pRoamProfile->AuthType.numEntries = 1;
8854 pRoamProfile->EncryptionType.numEntries = 1;
8855 pRoamProfile->EncryptionType.encryptionType[0] =
8856 eCSR_ENCRYPT_TYPE_WPI;
8857 pRoamProfile->mcEncryptionType.numEntries = 1;
8858 pRoamProfile->mcEncryptionType.
8859 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
8860 }
8861 }
8862#endif /* FEATURE_WLAN_WAPI */
8863#ifdef WLAN_FEATURE_GTK_OFFLOAD
8864 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -08008865 if ((QDF_STA_MODE == pAdapter->device_mode) ||
8866 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008867 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
8868 sizeof(tSirGtkOffloadParams));
8869 pHddStaCtx->gtkOffloadReqParams.ulFlags =
8870 GTK_OFFLOAD_DISABLE;
8871 }
8872#endif
8873 pRoamProfile->csrPersona = pAdapter->device_mode;
8874
8875 if (operatingChannel) {
8876 pRoamProfile->ChannelInfo.ChannelList =
8877 &operatingChannel;
8878 pRoamProfile->ChannelInfo.numOfChannels = 1;
8879 } else {
8880 pRoamProfile->ChannelInfo.ChannelList = NULL;
8881 pRoamProfile->ChannelInfo.numOfChannels = 0;
8882 }
Krunal Sonib4326f22016-03-10 13:05:51 -08008883 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008884 && operatingChannel) {
8885 /*
8886 * Need to post the IBSS power save parameters
8887 * to WMA. WMA will configure this parameters
8888 * to firmware if power save is enabled by the
8889 * firmware.
8890 */
8891 status = hdd_set_ibss_power_save_params(pAdapter);
8892
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308893 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008894 hddLog(LOGE,
8895 FL("Set IBSS Power Save Params Failed"));
8896 return -EINVAL;
8897 }
8898 hdd_select_cbmode(pAdapter, operatingChannel);
8899 }
8900
8901 if (pHddCtx->config->policy_manager_enabled &&
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008902 (true == cds_is_connection_in_progress())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008903 hdd_err("Connection refused: conn in progress");
8904 return -EINVAL;
8905 }
8906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008907 /* After 8-way handshake supplicant should give the scan command
8908 * in that it update the additional IEs, But because of scan
8909 * enhancements, the supplicant is not issuing the scan command now.
8910 * So the unicast frames which are sent from the host are not having
8911 * the additional IEs. If it is P2P CLIENT and there is no additional
8912 * IE present in roamProfile, then use the addtional IE form scan_info
8913 */
8914
Krunal Sonib4326f22016-03-10 13:05:51 -08008915 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008916 (!pRoamProfile->pAddIEScan)) {
8917 pRoamProfile->pAddIEScan =
8918 &pAdapter->scan_info.scanAddIE.addIEdata[0];
8919 pRoamProfile->nAddIEScanLength =
8920 pAdapter->scan_info.scanAddIE.length;
8921 }
8922 /*
8923 * When policy manager is enabled from ini file, we shouldn't
8924 * check for other concurrency rules.
8925 */
8926 if (!pHddCtx->config->policy_manager_enabled) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -08008927 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008928 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008929 pAdapter, pRoamProfile, &roamId))
8930 return 0;
8931 }
8932
Rajeev Kumar249ea8d2016-04-15 16:57:46 -07008933 if (pHddCtx->config->policy_manager_enabled &&
8934 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
8935 pRoamProfile))) {
8936 hdd_err("sap-sta conc will fail, can't allow sta");
8937 hdd_conn_set_connection_state(pAdapter,
8938 eConnectionState_NotConnected);
8939 return -ENOMEM;
8940 }
8941
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308942 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008943 if (!sme_config) {
8944 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -07008945 hdd_conn_set_connection_state(pAdapter,
8946 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008947 return -ENOMEM;
8948 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308949 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950 sme_get_config_param(pHddCtx->hHal, sme_config);
8951 /* These values are not sessionized. So, any change in these SME
8952 * configs on an older or parallel interface will affect the
8953 * cb mode. So, restoring the default INI params before starting
8954 * interfaces such as sta, cli etc.,
8955 */
8956 sme_config->csrConfig.channelBondingMode5GHz =
8957 pHddCtx->config->nChannelBondingMode5GHz;
8958 sme_config->csrConfig.channelBondingMode24GHz =
8959 pHddCtx->config->nChannelBondingMode24GHz;
8960 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308961 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +05308962 /*
8963 * Change conn_state to connecting before sme_roam_connect(),
8964 * because sme_roam_connect() has a direct path to call
8965 * hdd_sme_roam_callback(), which will change the conn_state
8966 * If direct path, conn_state will be accordingly changed to
8967 * NotConnected or Associated by either
8968 * hdd_association_completion_handler() or
8969 * hdd_dis_connect_handler() in sme_RoamCallback()if
8970 * sme_RomConnect is to be queued,
8971 * Connecting state will remain until it is completed.
8972 *
8973 * If connection state is not changed, connection state will
8974 * remain in eConnectionState_NotConnected state.
8975 * In hdd_association_completion_handler, "hddDisconInProgress"
8976 * is set to true if conn state is
8977 * eConnectionState_NotConnected.
8978 * If "hddDisconInProgress" is set to true then cfg80211 layer
8979 * is not informed of connect result indication which
8980 * is an issue.
8981 */
8982 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308983 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +05308984 hdd_conn_set_connection_state(pAdapter,
8985 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008986
8987 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
8988 pAdapter->sessionId, pRoamProfile,
8989 &roamId);
8990
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308991 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08008992 (QDF_STA_MODE == pAdapter->device_mode ||
8993 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008994 hddLog(LOGE,
8995 FL("sme_roam_connect (session %d) failed with "
8996 "status %d. -> NotConnected"),
8997 pAdapter->sessionId, status);
8998 /* change back to NotAssociated */
8999 hdd_conn_set_connection_state(pAdapter,
9000 eConnectionState_NotConnected);
9001 }
9002
9003 pRoamProfile->ChannelInfo.ChannelList = NULL;
9004 pRoamProfile->ChannelInfo.numOfChannels = 0;
9005
9006 } else {
9007 hddLog(LOGE, FL("No valid Roam profile"));
9008 return -EINVAL;
9009 }
9010 EXIT();
9011 return status;
9012}
9013
9014/**
9015 * wlan_hdd_cfg80211_set_auth_type() - set auth type
9016 * @pAdapter: Pointer to adapter
9017 * @auth_type: Auth type
9018 *
9019 * This function is used to set the authentication type (OPEN/SHARED).
9020 *
9021 * Return: 0 for success, non-zero for failure
9022 */
9023static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
9024 enum nl80211_auth_type auth_type)
9025{
9026 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9027 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009029 /*set authentication type */
9030 switch (auth_type) {
9031 case NL80211_AUTHTYPE_AUTOMATIC:
9032 hddLog(LOG1,
9033 FL("set authentication type to AUTOSWITCH"));
9034 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
9035 break;
9036
9037 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009038 case NL80211_AUTHTYPE_FT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009039 hddLog(LOG1,
9040 FL("set authentication type to OPEN"));
9041 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
9042 break;
9043
9044 case NL80211_AUTHTYPE_SHARED_KEY:
9045 hddLog(LOG1,
9046 FL("set authentication type to SHARED"));
9047 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
9048 break;
9049#ifdef FEATURE_WLAN_ESE
9050 case NL80211_AUTHTYPE_NETWORK_EAP:
9051 hddLog(LOG1,
9052 FL("set authentication type to CCKM WPA"));
9053 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
9054 break;
9055#endif
9056
9057 default:
9058 hddLog(LOGE,
9059 FL("Unsupported authentication type %d"), auth_type);
9060 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
9061 return -EINVAL;
9062 }
9063
9064 pWextState->roamProfile.AuthType.authType[0] =
9065 pHddStaCtx->conn_info.authType;
9066 return 0;
9067}
9068
9069/**
9070 * wlan_hdd_set_akm_suite() - set key management type
9071 * @pAdapter: Pointer to adapter
9072 * @key_mgmt: Key management type
9073 *
9074 * This function is used to set the key mgmt type(PSK/8021x).
9075 *
9076 * Return: 0 for success, non-zero for failure
9077 */
9078static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
9079{
9080 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9081
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009082#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
9083#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
9084 /*set key mgmt type */
9085 switch (key_mgmt) {
9086 case WLAN_AKM_SUITE_PSK:
9087 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009088 case WLAN_AKM_SUITE_FT_PSK:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009089 hddLog(LOG1, FL("setting key mgmt type to PSK"));
9090 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
9091 break;
9092
9093 case WLAN_AKM_SUITE_8021X_SHA256:
9094 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009095 case WLAN_AKM_SUITE_FT_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009096 hddLog(LOG1,
9097 FL("setting key mgmt type to 8021x"));
9098 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
9099 break;
9100#ifdef FEATURE_WLAN_ESE
9101#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
9102#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
9103 case WLAN_AKM_SUITE_CCKM:
9104 hddLog(LOG1,
9105 FL("setting key mgmt type to CCKM"));
9106 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
9107 break;
9108#endif
9109#ifndef WLAN_AKM_SUITE_OSEN
9110#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
9111#endif
9112 case WLAN_AKM_SUITE_OSEN:
9113 hddLog(LOG1,
9114 FL("setting key mgmt type to OSEN"));
9115 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
9116 break;
9117
9118 default:
9119 hddLog(LOGE,
9120 FL("Unsupported key mgmt type %d"), key_mgmt);
9121 return -EINVAL;
9122
9123 }
9124 return 0;
9125}
9126
9127/**
9128 * wlan_hdd_cfg80211_set_cipher() - set encryption type
9129 * @pAdapter: Pointer to adapter
9130 * @cipher: Cipher type
9131 * @ucast: Unicast flag
9132 *
9133 * This function is used to set the encryption type
9134 * (NONE/WEP40/WEP104/TKIP/CCMP).
9135 *
9136 * Return: 0 for success, non-zero for failure
9137 */
9138static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
9139 u32 cipher, bool ucast)
9140{
9141 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9142 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9143 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009145 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009146 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009147 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9148 } else {
9149
9150 /*set encryption method */
9151 switch (cipher) {
9152 case IW_AUTH_CIPHER_NONE:
9153 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
9154 break;
9155
9156 case WLAN_CIPHER_SUITE_WEP40:
9157 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
9158 break;
9159
9160 case WLAN_CIPHER_SUITE_WEP104:
9161 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
9162 break;
9163
9164 case WLAN_CIPHER_SUITE_TKIP:
9165 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
9166 break;
9167
9168 case WLAN_CIPHER_SUITE_CCMP:
9169 encryptionType = eCSR_ENCRYPT_TYPE_AES;
9170 break;
9171#ifdef FEATURE_WLAN_WAPI
9172 case WLAN_CIPHER_SUITE_SMS4:
9173 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
9174 break;
9175#endif
9176
9177#ifdef FEATURE_WLAN_ESE
9178 case WLAN_CIPHER_SUITE_KRK:
9179 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
9180 break;
9181#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9182 case WLAN_CIPHER_SUITE_BTK:
9183 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
9184 break;
9185#endif
9186#endif
9187 default:
9188 hddLog(LOGE,
9189 FL("Unsupported cipher type %d"), cipher);
9190 return -EOPNOTSUPP;
9191 }
9192 }
9193
9194 if (ucast) {
9195 hddLog(LOG1,
9196 FL("setting unicast cipher type to %d"), encryptionType);
9197 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
9198 pWextState->roamProfile.EncryptionType.numEntries = 1;
9199 pWextState->roamProfile.EncryptionType.encryptionType[0] =
9200 encryptionType;
9201 } else {
9202 hddLog(LOG1,
9203 FL("setting mcast cipher type to %d"), encryptionType);
9204 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
9205 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
9206 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
9207 encryptionType;
9208 }
9209
9210 return 0;
9211}
9212
9213/**
9214 * wlan_hdd_cfg80211_set_ie() - set IEs
9215 * @pAdapter: Pointer to adapter
9216 * @ie: Pointer ot ie
9217 * @ie: IE length
9218 *
9219 * Return: 0 for success, non-zero for failure
9220 */
9221int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
9222 size_t ie_len)
9223{
9224 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9225 const uint8_t *genie = ie;
9226 uint16_t remLen = ie_len;
9227#ifdef FEATURE_WLAN_WAPI
9228 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
9229 u16 *tmp;
9230 uint16_t akmsuiteCount;
9231 int *akmlist;
9232#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009233
9234 /* clear previous assocAddIE */
9235 pWextState->assocAddIE.length = 0;
9236 pWextState->roamProfile.bWPSAssociation = false;
9237 pWextState->roamProfile.bOSENAssociation = false;
9238
9239 while (remLen >= 2) {
9240 uint16_t eLen = 0;
9241 uint8_t elementId;
9242 elementId = *genie++;
9243 eLen = *genie++;
9244 remLen -= 2;
9245
9246 hddLog(LOG1, FL("IE[0x%X], LEN[%d]"), elementId, eLen);
9247
9248 switch (elementId) {
9249 case DOT11F_EID_WPA:
9250 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
9251 hddLog(LOGE, FL("Invalid WPA IE"));
9252 return -EINVAL;
9253 } else if (0 ==
9254 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
9255 uint16_t curAddIELen =
9256 pWextState->assocAddIE.length;
9257 hddLog(LOG1,
9258 FL("Set WPS IE(len %d)"), eLen + 2);
9259
9260 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9261 (pWextState->assocAddIE.length + eLen)) {
9262 hddLog(LOGE,
9263 FL("Cannot accommodate assocAddIE. Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309264 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009265 return -ENOMEM;
9266 }
9267 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
9268 memcpy(pWextState->assocAddIE.addIEdata +
9269 curAddIELen, genie - 2, eLen + 2);
9270 pWextState->assocAddIE.length += eLen + 2;
9271
9272 pWextState->roamProfile.bWPSAssociation = true;
9273 pWextState->roamProfile.pAddIEAssoc =
9274 pWextState->assocAddIE.addIEdata;
9275 pWextState->roamProfile.nAddIEAssocLength =
9276 pWextState->assocAddIE.length;
9277 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
9278 hddLog(LOG1,
9279 FL("Set WPA IE (len %d)"), eLen + 2);
9280 memset(pWextState->WPARSNIE, 0,
9281 MAX_WPA_RSN_IE_LEN);
9282 memcpy(pWextState->WPARSNIE, genie - 2,
9283 (eLen + 2));
9284 pWextState->roamProfile.pWPAReqIE =
9285 pWextState->WPARSNIE;
9286 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
9287 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
9288 P2P_OUI_TYPE_SIZE))) {
9289 uint16_t curAddIELen =
9290 pWextState->assocAddIE.length;
9291 hddLog(LOG1,
9292 FL("Set P2P IE(len %d)"), eLen + 2);
9293
9294 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9295 (pWextState->assocAddIE.length + eLen)) {
9296 hddLog(LOGE,
9297 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309298 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 return -ENOMEM;
9300 }
9301 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
9302 memcpy(pWextState->assocAddIE.addIEdata +
9303 curAddIELen, genie - 2, eLen + 2);
9304 pWextState->assocAddIE.length += eLen + 2;
9305
9306 pWextState->roamProfile.pAddIEAssoc =
9307 pWextState->assocAddIE.addIEdata;
9308 pWextState->roamProfile.nAddIEAssocLength =
9309 pWextState->assocAddIE.length;
9310 }
9311#ifdef WLAN_FEATURE_WFD
9312 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
9313 WFD_OUI_TYPE_SIZE)) &&
9314 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -08009315 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009316 pAdapter->device_mode)) {
9317 uint16_t curAddIELen =
9318 pWextState->assocAddIE.length;
9319 hddLog(LOG1,
9320 FL("Set WFD IE(len %d)"), eLen + 2);
9321
9322 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9323 (pWextState->assocAddIE.length + eLen)) {
9324 hddLog(LOGE,
9325 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309326 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009327 return -ENOMEM;
9328 }
9329 /* WFD IE is saved to Additional IE ; it should
9330 * be accumulated to handle WPS IE + P2P IE +
9331 * WFD IE */
9332 memcpy(pWextState->assocAddIE.addIEdata +
9333 curAddIELen, genie - 2, eLen + 2);
9334 pWextState->assocAddIE.length += eLen + 2;
9335
9336 pWextState->roamProfile.pAddIEAssoc =
9337 pWextState->assocAddIE.addIEdata;
9338 pWextState->roamProfile.nAddIEAssocLength =
9339 pWextState->assocAddIE.length;
9340 }
9341#endif
9342 /* Appending HS 2.0 Indication Element in Assiciation Request */
9343 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
9344 HS20_OUI_TYPE_SIZE))) {
9345 uint16_t curAddIELen =
9346 pWextState->assocAddIE.length;
9347 hddLog(LOG1,
9348 FL("Set HS20 IE(len %d)"), eLen + 2);
9349
9350 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9351 (pWextState->assocAddIE.length + eLen)) {
9352 hddLog(LOGE,
9353 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309354 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009355 return -ENOMEM;
9356 }
9357 memcpy(pWextState->assocAddIE.addIEdata +
9358 curAddIELen, genie - 2, eLen + 2);
9359 pWextState->assocAddIE.length += eLen + 2;
9360
9361 pWextState->roamProfile.pAddIEAssoc =
9362 pWextState->assocAddIE.addIEdata;
9363 pWextState->roamProfile.nAddIEAssocLength =
9364 pWextState->assocAddIE.length;
9365 }
9366 /* Appending OSEN Information Element in Assiciation Request */
9367 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
9368 OSEN_OUI_TYPE_SIZE))) {
9369 uint16_t curAddIELen =
9370 pWextState->assocAddIE.length;
9371 hddLog(LOG1,
9372 FL("Set OSEN IE(len %d)"), eLen + 2);
9373
9374 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9375 (pWextState->assocAddIE.length + eLen)) {
9376 hddLog(LOGE,
9377 FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309378 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009379 return -ENOMEM;
9380 }
9381 memcpy(pWextState->assocAddIE.addIEdata +
9382 curAddIELen, genie - 2, eLen + 2);
9383 pWextState->assocAddIE.length += eLen + 2;
9384
9385 pWextState->roamProfile.bOSENAssociation = true;
9386 pWextState->roamProfile.pAddIEAssoc =
9387 pWextState->assocAddIE.addIEdata;
9388 pWextState->roamProfile.nAddIEAssocLength =
9389 pWextState->assocAddIE.length;
9390 } else {
9391 uint16_t add_ie_len =
9392 pWextState->assocAddIE.length;
9393
9394 hdd_info("Set OSEN IE(len %d)", eLen + 2);
9395
9396 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9397 (pWextState->assocAddIE.length + eLen)) {
9398 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309399 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400 return -ENOMEM;
9401 }
9402
9403 memcpy(pWextState->assocAddIE.addIEdata +
9404 add_ie_len, genie - 2, eLen + 2);
9405 pWextState->assocAddIE.length += eLen + 2;
9406
9407 pWextState->roamProfile.pAddIEAssoc =
9408 pWextState->assocAddIE.addIEdata;
9409 pWextState->roamProfile.nAddIEAssocLength =
9410 pWextState->assocAddIE.length;
9411 }
9412 break;
9413 case DOT11F_EID_RSN:
9414 hddLog(LOG1, FL("Set RSN IE(len %d)"), eLen + 2);
9415 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
9416 memcpy(pWextState->WPARSNIE, genie - 2,
9417 (eLen + 2));
9418 pWextState->roamProfile.pRSNReqIE =
9419 pWextState->WPARSNIE;
9420 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
9421 break;
9422 /*
9423 * Appending Extended Capabilities with Interworking bit set
9424 * in Assoc Req.
9425 *
9426 * In assoc req this EXT Cap will only be taken into account if
9427 * interworkingService bit is set to 1. Currently
9428 * driver is only interested in interworkingService capability
9429 * from supplicant. If in future any other EXT Cap info is
9430 * required from supplicat, it needs to be handled while
9431 * sending Assoc Req in LIM.
9432 */
9433 case DOT11F_EID_EXTCAP:
9434 {
9435 uint16_t curAddIELen =
9436 pWextState->assocAddIE.length;
9437 hddLog(LOG1,
9438 FL("Set Extended CAPS IE(len %d)"), eLen + 2);
9439
9440 if (SIR_MAC_MAX_ADD_IE_LENGTH <
9441 (pWextState->assocAddIE.length + eLen)) {
9442 hddLog(LOGE, FL("Cannot accommodate assocAddIE Need bigger buffer space"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309443 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009444 return -ENOMEM;
9445 }
9446 memcpy(pWextState->assocAddIE.addIEdata +
9447 curAddIELen, genie - 2, eLen + 2);
9448 pWextState->assocAddIE.length += eLen + 2;
9449
9450 pWextState->roamProfile.pAddIEAssoc =
9451 pWextState->assocAddIE.addIEdata;
9452 pWextState->roamProfile.nAddIEAssocLength =
9453 pWextState->assocAddIE.length;
9454 break;
9455 }
9456#ifdef FEATURE_WLAN_WAPI
9457 case WLAN_EID_WAPI:
9458 /* Setting WAPI Mode to ON=1 */
9459 pAdapter->wapi_info.nWapiMode = 1;
9460 hddLog(LOG1,
9461 FL("WAPI MODE IS %u"), pAdapter->wapi_info.nWapiMode);
9462 tmp = (u16 *) ie;
9463 tmp = tmp + 2; /* Skip element Id and Len, Version */
9464 akmsuiteCount = WPA_GET_LE16(tmp);
9465 tmp = tmp + 1;
9466 akmlist = (int *)(tmp);
9467 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
9468 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
9469 } else {
9470 hddLog(LOGE,
9471 FL("Invalid akmSuite count"));
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309472 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473 return -EINVAL;
9474 }
9475
9476 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
9477 hddLog(LOG1,
9478 FL("WAPI AUTH MODE SET TO PSK"));
9479 pAdapter->wapi_info.wapiAuthMode =
9480 WAPI_AUTH_MODE_PSK;
9481 }
9482 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
9483 hddLog(LOG1,
9484 FL("WAPI AUTH MODE SET TO CERTIFICATE"));
9485 pAdapter->wapi_info.wapiAuthMode =
9486 WAPI_AUTH_MODE_CERT;
9487 }
9488 break;
9489#endif
9490 default:
9491 hddLog(LOGE,
9492 FL("Set UNKNOWN IE %X"), elementId);
9493 /* when Unknown IE is received we should break and continue
9494 * to the next IE in the buffer instead we were returning
9495 * so changing this to break */
9496 break;
9497 }
9498 genie += eLen;
9499 remLen -= eLen;
9500 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501 return 0;
9502}
9503
9504/**
9505 * hdd_is_wpaie_present() - check for WPA ie
9506 * @ie: Pointer to ie
9507 * @ie_len: Ie length
9508 *
9509 * Parse the received IE to find the WPA IE
9510 *
9511 * Return: true if wpa ie is found else false
9512 */
9513static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
9514{
9515 uint8_t eLen = 0;
9516 uint16_t remLen = ie_len;
9517 uint8_t elementId = 0;
9518
9519 while (remLen >= 2) {
9520 elementId = *ie++;
9521 eLen = *ie++;
9522 remLen -= 2;
9523 if (eLen > remLen) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309524 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009525 "%s: IE length is wrong %d", __func__, eLen);
9526 return false;
9527 }
9528 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
9529 /* OUI - 0x00 0X50 0XF2
9530 * WPA Information Element - 0x01
9531 * WPA version - 0x01
9532 */
9533 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
9534 return true;
9535 }
9536 ie += eLen;
9537 remLen -= eLen;
9538 }
9539 return false;
9540}
9541
9542/**
9543 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
9544 * @pAdapter: Pointer to adapter
9545 * @req: Pointer to security parameters
9546 *
9547 * Return: 0 for success, non-zero for failure
9548 */
9549int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
9550 struct cfg80211_connect_params *req)
9551{
9552 int status = 0;
9553 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9554 ENTER();
9555
9556 /*set wpa version */
9557 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
9558
9559 if (req->crypto.wpa_versions) {
9560 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
9561 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
9562 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
9563 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
9564 }
9565 }
9566
9567 hddLog(LOG1, FL("set wpa version to %d"), pWextState->wpaVersion);
9568
9569 /*set authentication type */
9570 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
9571
9572 if (0 > status) {
9573 hddLog(LOGE, FL("failed to set authentication type "));
9574 return status;
9575 }
9576
9577 /*set key mgmt type */
9578 if (req->crypto.n_akm_suites) {
9579 status =
9580 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
9581 if (0 > status) {
9582 hddLog(LOGE, FL("failed to set akm suite"));
9583 return status;
9584 }
9585 }
9586
9587 /*set pairwise cipher type */
9588 if (req->crypto.n_ciphers_pairwise) {
9589 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
9590 req->crypto.
9591 ciphers_pairwise[0],
9592 true);
9593 if (0 > status) {
9594 hddLog(LOGE, FL("failed to set unicast cipher type"));
9595 return status;
9596 }
9597 } else {
9598 /*Reset previous cipher suite to none */
9599 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
9600 if (0 > status) {
9601 hddLog(LOGE, FL("failed to set unicast cipher type"));
9602 return status;
9603 }
9604 }
9605
9606 /*set group cipher type */
9607 status =
9608 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
9609 false);
9610
9611 if (0 > status) {
9612 hddLog(LOGE, FL("failed to set mcast cipher type"));
9613 return status;
9614 }
9615#ifdef WLAN_FEATURE_11W
9616 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
9617#endif
9618
9619 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
9620 if (req->ie_len) {
9621 status =
9622 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
9623 if (0 > status) {
9624 hddLog(LOGE, FL("failed to parse the WPA/RSN IE"));
9625 return status;
9626 }
9627 }
9628
9629 /*incase of WEP set default key information */
9630 if (req->key && req->key_len) {
9631 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
9632 || (WLAN_CIPHER_SUITE_WEP104 ==
9633 req->crypto.ciphers_pairwise[0])
9634 ) {
9635 if (IW_AUTH_KEY_MGMT_802_1X
9636 ==
9637 (pWextState->
9638 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
9639 hddLog(LOGE,
9640 FL("Dynamic WEP not supported"));
9641 return -EOPNOTSUPP;
9642 } else {
9643 u8 key_len = req->key_len;
9644 u8 key_idx = req->key_idx;
9645
9646 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
9647 key_len)
9648 && (CSR_MAX_NUM_KEY > key_idx)
9649 ) {
9650 hddLog(LOG1,
9651 FL("setting default wep key, key_idx = %hu key_len %hu"),
9652 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309653 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009654 Keys.
9655 KeyMaterial[key_idx][0],
9656 req->key, key_len);
9657 pWextState->roamProfile.Keys.
9658 KeyLength[key_idx] = (u8) key_len;
9659 pWextState->roamProfile.Keys.
9660 defaultIndex = (u8) key_idx;
9661 }
9662 }
9663 }
9664 }
9665
9666 return status;
9667}
9668
9669/**
9670 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
9671 * @pAdapter: Pointer to adapter
9672 *
9673 * This function is used to disconnect from previous connection
9674 *
9675 * Return: 0 for success, non-zero for failure
9676 */
9677static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
9678{
9679 unsigned long rc;
9680 hdd_station_ctx_t *pHddStaCtx;
9681 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309682 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683
9684 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9685
9686 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
9687
9688 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +05309689 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
9690 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
9691 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009692 hdd_conn_set_connection_state(pAdapter,
9693 eConnectionState_Disconnecting);
9694 /* Issue disconnect to CSR */
9695 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309696
9697 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9698 pAdapter->sessionId,
9699 eCSR_DISCONNECT_REASON_UNSPECIFIED);
9700 /*
9701 * Wait here instead of returning directly, this will block the
9702 * next connect command and allow processing of the scan for
9703 * ssid and the previous connect command in CSR. Else we might
9704 * hit some race conditions leading to SME and HDD out of sync.
9705 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309706 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309707 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
9708 } else if (0 != status) {
9709 hdd_err("csrRoamDisconnect failure, returned %d",
9710 (int)status);
9711 pHddStaCtx->staDebugState = status;
9712 result = -EINVAL;
9713 goto disconnected;
9714 }
9715
9716 rc = wait_for_completion_timeout(
9717 &pAdapter->disconnect_comp_var,
9718 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309719 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309720 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
9721 pAdapter->sessionId, pHddStaCtx->staDebugState);
9722 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 }
9724 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309725 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009726 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309727 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009728 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309729 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009730 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309731 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732 }
9733 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309734disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309735 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
9736 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009737}
9738
9739/**
9740 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
9741 * @wiphy: Pointer to wiphy
9742 * @dev: Pointer to network device
9743 * @req: Pointer to cfg80211 connect request
9744 *
9745 * This function is used to start the association process
9746 *
9747 * Return: 0 for success, non-zero for failure
9748 */
9749static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
9750 struct net_device *ndev,
9751 struct cfg80211_connect_params *req)
9752{
9753 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05309754 u16 channel;
9755#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
9756 const u8 *bssid_hint = req->bssid_hint;
9757#else
9758 const u8 *bssid_hint = NULL;
9759#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9761 hdd_context_t *pHddCtx;
9762
9763 ENTER();
9764
Anurag Chouhan6d760662016-02-20 16:05:43 +05309765 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009766 hddLog(LOGE, FL("Command not allowed in FTM mode"));
9767 return -EINVAL;
9768 }
9769
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309770 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009771 TRACE_CODE_HDD_CFG80211_CONNECT,
9772 pAdapter->sessionId, pAdapter->device_mode));
9773 hddLog(LOG1, FL("Device_mode %s(%d)"),
9774 hdd_device_mode_to_string(pAdapter->device_mode),
9775 pAdapter->device_mode);
9776
Krunal Sonib4326f22016-03-10 13:05:51 -08009777 if (pAdapter->device_mode != QDF_STA_MODE &&
9778 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009779 hddLog(LOGE, FL("Device_mode %s(%d) is not supported"),
9780 hdd_device_mode_to_string(pAdapter->device_mode),
9781 pAdapter->device_mode);
9782 return -EINVAL;
9783 }
9784
9785 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9786 if (!pHddCtx) {
9787 hddLog(LOGE, FL("HDD context is null"));
9788 return -EINVAL;
9789 }
9790
9791 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309792 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009793 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009794 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009795 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -08009796 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009797 pAdapter->device_mode),
9798 req->channel->hw_value, HW_MODE_20_MHZ)) {
9799 hdd_err("This concurrency combination is not allowed");
9800 return -ECONNREFUSED;
9801 }
9802 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009803 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -08009804 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009805 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
9806 hdd_err("This concurrency combination is not allowed");
9807 return -ECONNREFUSED;
9808 }
9809 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810 wlan_hdd_disable_roaming(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009811
9812 /*Try disconnecting if already in connected state */
9813 status = wlan_hdd_try_disconnect(pAdapter);
9814 if (0 > status) {
9815 hddLog(LOGE,
9816 FL("Failed to disconnect the existing connection"));
9817 return -EALREADY;
9818 }
9819
9820 /*initialise security parameters */
9821 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
9822
9823 if (0 > status) {
9824 hddLog(LOGE,
9825 FL("failed to set security params"));
9826 return status;
9827 }
9828
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +05309829 if (req->channel)
9830 channel = req->channel->hw_value;
9831 else
9832 channel = 0;
9833 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
9834 req->ssid_len, req->bssid,
9835 bssid_hint, channel);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009836 if (0 > status) {
9837 hddLog(LOGE, FL("connect failed"));
9838 return status;
9839 }
9840 EXIT();
9841 return status;
9842}
9843
9844/**
9845 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
9846 * @wiphy: Pointer to wiphy
9847 * @dev: Pointer to network device
9848 * @req: Pointer to cfg80211 connect request
9849 *
9850 * Return: 0 for success, non-zero for failure
9851 */
9852static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
9853 struct net_device *ndev,
9854 struct cfg80211_connect_params *req)
9855{
9856 int ret;
9857 cds_ssr_protect(__func__);
9858 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
9859 cds_ssr_unprotect(__func__);
9860
9861 return ret;
9862}
9863
9864/**
9865 * wlan_hdd_disconnect() - hdd disconnect api
9866 * @pAdapter: Pointer to adapter
9867 * @reason: Disconnect reason code
9868 *
9869 * This function is used to issue a disconnect request to SME
9870 *
9871 * Return: 0 for success, non-zero for failure
9872 */
9873int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
9874{
9875 int status, result = 0;
9876 unsigned long rc;
9877 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9878 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9879
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309880 ENTER();
9881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 status = wlan_hdd_validate_context(pHddCtx);
9883
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309884 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009885 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009886
9887 /*stop tx queues */
9888 hddLog(LOG1, FL("Disabling queues"));
9889 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
9890 WLAN_CONTROL_PATH);
9891 hddLog(LOG1,
9892 FL("Set HDD connState to eConnectionState_Disconnecting"));
9893 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
9894 INIT_COMPLETION(pAdapter->disconnect_comp_var);
9895
9896 /*issue disconnect */
9897
9898 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
9899 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +05309900 /*
9901 * Wait here instead of returning directly, this will block the next
9902 * connect command and allow processing of the scan for ssid and
9903 * the previous connect command in CSR. Else we might hit some
9904 * race conditions leading to SME and HDD out of sync.
9905 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309906 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +05309907 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009908 } else if (0 != status) {
9909 hddLog(LOGE,
9910 FL("csr_roam_disconnect failure, returned %d"),
9911 (int)status);
9912 pHddStaCtx->staDebugState = status;
9913 result = -EINVAL;
9914 goto disconnected;
9915 }
9916 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
9917 msecs_to_jiffies
9918 (WLAN_WAIT_TIME_DISCONNECT));
9919
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309920 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009921 hddLog(LOGE,
9922 FL("Failed to disconnect, timed out"));
9923 result = -ETIMEDOUT;
9924 }
9925disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
9927#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
9928 /* Sending disconnect event to userspace for kernel version < 3.11
9929 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
9930 */
9931 hddLog(LOG1, FL("Send disconnected event to userspace"));
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +05309932 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
9933 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009934#endif
9935
9936 return result;
9937}
9938
9939/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009940 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
9941 * @reason: ieee80211 reason code.
9942 *
9943 * This utility function helps log string conversion of reason code.
9944 *
9945 * Return: string conversion of reason code, if match found;
9946 * "Unknown" otherwise.
9947 */
9948static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
9949{
9950 switch (reason) {
9951 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
9952 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
9953 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
9954 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
9955 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
9956 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
9957 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
9958 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
9959 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
9960 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
9961 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
9962 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
9963 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
9964 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
9965 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
9966 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
9967 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
9968 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
9969 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
9970 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
9971 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
9972 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
9973 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
9974 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
9975 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
9976 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
9977 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
9978 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
9979 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
9980 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
9981 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
9982 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
9983 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
9984 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
9985 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
9986 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
9987 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
9988 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
9989 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
9990 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
9991 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
9992 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
9993 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
9994 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
9995 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
9996 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
9997 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
9998 default:
9999 return "Unknown";
10000 }
10001}
10002
10003/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
10005 * @wiphy: Pointer to wiphy
10006 * @dev: Pointer to network device
10007 * @reason: Disconnect reason code
10008 *
10009 * This function is used to issue a disconnect request to SME
10010 *
10011 * Return: 0 for success, non-zero for failure
10012 */
10013static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
10014 struct net_device *dev, u16 reason)
10015{
10016 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10017 int status;
10018 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10019 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10020#ifdef FEATURE_WLAN_TDLS
10021 uint8_t staIdx;
10022#endif
10023
10024 ENTER();
10025
Anurag Chouhan6d760662016-02-20 16:05:43 +053010026 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10028 return -EINVAL;
10029 }
10030
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010031 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010032 TRACE_CODE_HDD_CFG80211_DISCONNECT,
10033 pAdapter->sessionId, reason));
10034 hddLog(LOG1, FL("Device_mode %s(%d) reason code(%d)"),
10035 hdd_device_mode_to_string(pAdapter->device_mode),
10036 pAdapter->device_mode, reason);
10037
10038 status = wlan_hdd_validate_context(pHddCtx);
10039
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010040 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042
10043 /* Issue disconnect request to SME, if station is in connected state */
10044 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
10045 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
10046 eCsrRoamDisconnectReason reasonCode =
10047 eCSR_DISCONNECT_REASON_UNSPECIFIED;
10048 hdd_scaninfo_t *pScanInfo;
10049
10050 switch (reason) {
10051 case WLAN_REASON_MIC_FAILURE:
10052 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
10053 break;
10054
10055 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
10056 case WLAN_REASON_DISASSOC_AP_BUSY:
10057 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
10058 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
10059 break;
10060
10061 case WLAN_REASON_PREV_AUTH_NOT_VALID:
10062 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
10063 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
10064 break;
10065
10066 case WLAN_REASON_DEAUTH_LEAVING:
10067 reasonCode =
10068 pHddCtx->config->
10069 gEnableDeauthToDisassocMap ?
10070 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
10071 eCSR_DISCONNECT_REASON_DEAUTH;
10072 break;
10073 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
10074 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
10075 break;
10076 default:
10077 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
10078 break;
10079 }
10080 hddLog(LOG1,
10081 FL("convert to internal reason %d to reasonCode %d"),
10082 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010083 pScanInfo = &pAdapter->scan_info;
10084 if (pScanInfo->mScanPending) {
10085 hddLog(LOG1,
10086 FL("Disconnect is in progress, Aborting Scan"));
10087 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10088 eCSR_SCAN_ABORT_DEFAULT);
10089 }
10090#ifdef FEATURE_WLAN_TDLS
10091 /* First clean up the tdls peers if any */
10092 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
10093 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
10094 pAdapter->sessionId)
10095 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
10096 uint8_t *mac;
10097 mac =
10098 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
10099 hddLog(LOG1,
10100 "%s: call sme_delete_tdls_peer_sta staId %d sessionId %d "
10101 MAC_ADDRESS_STR, __func__,
10102 pHddCtx->tdlsConnInfo[staIdx].staId,
10103 pAdapter->sessionId,
10104 MAC_ADDR_ARRAY(mac));
10105 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
10106 (pAdapter),
10107 pAdapter->sessionId, mac);
10108 }
10109 }
10110#endif
10111 hddLog(LOG1, FL("Disconnecting with reasoncode:%u"),
10112 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010113 hdd_info("Disconnect request from user space with reason: %s",
10114 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010115 status = wlan_hdd_disconnect(pAdapter, reasonCode);
10116 if (0 != status) {
10117 hddLog(LOGE,
10118 FL("failure, returned %d"), status);
10119 return -EINVAL;
10120 }
10121 } else {
10122 hddLog(LOGE,
10123 FL("unexpected cfg disconnect called while in state (%d)"),
10124 pHddStaCtx->conn_info.connState);
10125 }
10126
10127 return status;
10128}
10129
10130/**
10131 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
10132 * @wiphy: Pointer to wiphy
10133 * @dev: Pointer to network device
10134 * @reason: Disconnect reason code
10135 *
10136 * Return: 0 for success, non-zero for failure
10137 */
10138static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
10139 struct net_device *dev, u16 reason)
10140{
10141 int ret;
10142 cds_ssr_protect(__func__);
10143 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
10144 cds_ssr_unprotect(__func__);
10145
10146 return ret;
10147}
10148
10149/**
10150 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
10151 * @pAdapter: Pointer to adapter
10152 * @param: Pointer to IBSS parameters
10153 *
10154 * This function is used to initialize the security settings in IBSS mode
10155 *
10156 * Return: 0 for success, non-zero for failure
10157 */
10158static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
10159 struct cfg80211_ibss_params
10160 *params)
10161{
10162 int status = 0;
10163 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10164 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
10165 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10166
10167 ENTER();
10168
10169 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010170 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 pHddStaCtx->ibss_enc_key_installed = 0;
10172
10173 if (params->ie_len && (NULL != params->ie)) {
10174 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
10175 params->ie_len, WLAN_EID_RSN)) {
10176 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
10177 encryptionType = eCSR_ENCRYPT_TYPE_AES;
10178 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
10179 tDot11fIEWPA dot11WPAIE;
10180 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
10181 u8 *ie;
10182
10183 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
10184 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
10185 params->ie_len,
10186 DOT11F_EID_WPA);
10187 if (NULL != ie) {
10188 pWextState->wpaVersion =
10189 IW_AUTH_WPA_VERSION_WPA;
10190 /* Unpack the WPA IE */
10191 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
10192 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
10193 &ie[2 + 4],
10194 ie[1] - 4, &dot11WPAIE);
10195 /*Extract the multicast cipher, the encType for unicast
10196 cipher for wpa-none is none */
10197 encryptionType =
10198 hdd_translate_wpa_to_csr_encryption_type
10199 (dot11WPAIE.multicast_cipher);
10200 }
10201 }
10202
10203 status =
10204 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
10205 params->ie_len);
10206
10207 if (0 > status) {
10208 hddLog(LOGE, FL("failed to parse WPA/RSN IE"));
10209 return status;
10210 }
10211 }
10212
10213 pWextState->roamProfile.AuthType.authType[0] =
10214 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
10215
10216 if (params->privacy) {
10217 /* Security enabled IBSS, At this time there is no information
10218 * available about the security paramters, so initialise the
10219 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
10220 * The correct security parameters will be updated later in
10221 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
10222 * set inorder enable privacy bit in beacons
10223 */
10224
10225 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10226 }
10227 hddLog(LOG2, FL("encryptionType=%d"), encryptionType);
10228 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
10229 pWextState->roamProfile.EncryptionType.numEntries = 1;
10230 pWextState->roamProfile.EncryptionType.encryptionType[0] =
10231 encryptionType;
10232 return status;
10233}
10234
10235/**
10236 * __wlan_hdd_cfg80211_join_ibss() - join ibss
10237 * @wiphy: Pointer to wiphy
10238 * @dev: Pointer to network device
10239 * @param: Pointer to IBSS join parameters
10240 *
10241 * This function is used to create/join an IBSS network
10242 *
10243 * Return: 0 for success, non-zero for failure
10244 */
10245static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
10246 struct net_device *dev,
10247 struct cfg80211_ibss_params *params)
10248{
10249 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10250 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10251 tCsrRoamProfile *pRoamProfile;
10252 int status;
10253 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10254 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053010255 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010256 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257
10258 ENTER();
10259
Anurag Chouhan6d760662016-02-20 16:05:43 +053010260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10262 return -EINVAL;
10263 }
10264
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010265 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
10267 pAdapter->sessionId, pAdapter->device_mode));
10268 hddLog(LOG1, FL("Device_mode %s(%d)"),
10269 hdd_device_mode_to_string(pAdapter->device_mode),
10270 pAdapter->device_mode);
10271
10272 status = wlan_hdd_validate_context(pHddCtx);
10273
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010274 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010275 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276
10277 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053010278 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010279 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10280 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10281 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10282 int indx;
10283
10284 /* Get channel number */
10285 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010286 params->
10287 chandef.
10288 chan->
10289 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290
10291 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10292 validChan, &numChans)) {
10293 hddLog(LOGE, FL("No valid channel list"));
10294 return -EOPNOTSUPP;
10295 }
10296
10297 for (indx = 0; indx < numChans; indx++) {
10298 if (channelNum == validChan[indx]) {
10299 break;
10300 }
10301 }
10302 if (indx >= numChans) {
10303 hddLog(LOGE,
10304 FL("Not valid Channel %d"), channelNum);
10305 return -EINVAL;
10306 }
10307 }
10308
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010309 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010310 HW_MODE_20_MHZ)) {
10311 hdd_err("This concurrency combination is not allowed");
10312 return -ECONNREFUSED;
10313 }
10314 if (pHddCtx->config->policy_manager_enabled) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010315 status = qdf_reset_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010316 if (!QDF_IS_STATUS_SUCCESS(status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010317 hdd_err("ERR: clear event failed");
10318
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +053010319 status = cds_current_connections_update(pAdapter->sessionId,
10320 channelNum,
Chandrasekaran, Manishekarce2172e2016-02-18 16:12:43 +053010321 SIR_UPDATE_REASON_JOIN_IBSS);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010322 if (QDF_STATUS_E_FAILURE == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 hdd_err("ERROR: connections update failed!!");
10324 return -EINVAL;
10325 }
10326
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010327 if (QDF_STATUS_SUCCESS == status) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010328 status = qdf_wait_for_connection_update();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010329 if (!QDF_IS_STATUS_SUCCESS(status)) {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010330 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010331 return -EINVAL;
10332 }
10333 }
10334 }
10335
10336 /*Try disconnecting if already in connected state */
10337 status = wlan_hdd_try_disconnect(pAdapter);
10338 if (0 > status) {
10339 hddLog(LOGE,
10340 FL("Failed to disconnect the existing IBSS connection"));
10341 return -EALREADY;
10342 }
10343
10344 pRoamProfile = &pWextState->roamProfile;
10345
10346 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
10347 hddLog(LOGE,
10348 FL("Interface type is not set to IBSS"));
10349 return -EINVAL;
10350 }
10351
10352 /* enable selected protection checks in IBSS mode */
10353 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
10354
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010355 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356 WNI_CFG_IBSS_ATIM_WIN_SIZE,
10357 pHddCtx->config->
10358 ibssATIMWinSize)) {
10359 hddLog(LOGE,
10360 FL("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM"));
10361 }
10362
10363 /* BSSID is provided by upper layers hence no need to AUTO generate */
10364 if (NULL != params->bssid) {
10365 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010366 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367 hddLog(LOGE,
10368 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
10369 return -EIO;
10370 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010371 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
10373 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010374 == QDF_STATUS_E_FAILURE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010375 hddLog(LOGE,
10376 FL("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID"));
10377 return -EIO;
10378 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053010379 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010380 }
10381 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
10382 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
10383 pRoamProfile->beaconInterval = params->beacon_interval;
10384 else {
10385 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
10386 hddLog(LOG2,
10387 FL("input beacon interval %d TU is invalid, use default %d TU"),
10388 params->beacon_interval, pRoamProfile->beaconInterval);
10389 }
10390
10391 /* Set Channel */
10392 if (channelNum) {
10393 /* Set the Operational Channel */
10394 hddLog(LOG2, FL("set channel %d"), channelNum);
10395 pRoamProfile->ChannelInfo.numOfChannels = 1;
10396 pHddStaCtx->conn_info.operationChannel = channelNum;
10397 pRoamProfile->ChannelInfo.ChannelList =
10398 &pHddStaCtx->conn_info.operationChannel;
10399 }
10400
10401 /* Initialize security parameters */
10402 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
10403 if (status < 0) {
10404 hddLog(LOGE,
10405 FL("failed to set security parameters"));
10406 return status;
10407 }
10408
10409 /* Issue connect start */
10410 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
10411 params->ssid_len,
10412 bssid.bytes,
10413 NULL,
10414 pHddStaCtx->conn_info.
10415 operationChannel);
10416
10417 if (0 > status) {
10418 hddLog(LOGE, FL("connect failed"));
10419 return status;
10420 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010421 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 return 0;
10423}
10424
10425/**
10426 * wlan_hdd_cfg80211_join_ibss() - join ibss
10427 * @wiphy: Pointer to wiphy
10428 * @dev: Pointer to network device
10429 * @param: Pointer to IBSS join parameters
10430 *
10431 * This function is used to create/join an IBSS network
10432 *
10433 * Return: 0 for success, non-zero for failure
10434 */
10435static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
10436 struct net_device *dev,
10437 struct cfg80211_ibss_params *params)
10438{
10439 int ret = 0;
10440
10441 cds_ssr_protect(__func__);
10442 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
10443 cds_ssr_unprotect(__func__);
10444
10445 return ret;
10446}
10447
10448/**
10449 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
10450 * @wiphy: Pointer to wiphy
10451 * @dev: Pointer to network device
10452 *
10453 * This function is used to leave an IBSS network
10454 *
10455 * Return: 0 for success, non-zero for failure
10456 */
10457static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
10458 struct net_device *dev)
10459{
10460 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10461 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10462 tCsrRoamProfile *pRoamProfile;
10463 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10464 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010465 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053010466 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080010467 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010468
10469 ENTER();
10470
Anurag Chouhan6d760662016-02-20 16:05:43 +053010471 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010472 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10473 return -EINVAL;
10474 }
10475
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010476 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010477 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
10478 pAdapter->sessionId,
10479 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
10480 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010481 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010482 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010483
10484 hddLog(LOG1, FL("Device_mode %s(%d)"),
10485 hdd_device_mode_to_string(pAdapter->device_mode),
10486 pAdapter->device_mode);
10487 if (NULL == pWextState) {
10488 hddLog(LOGE, FL("Data Storage Corruption"));
10489 return -EIO;
10490 }
10491
10492 pRoamProfile = &pWextState->roamProfile;
10493
10494 /* Issue disconnect only if interface type is set to IBSS */
10495 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
10496 hddLog(LOGE,
10497 FL("BSS Type is not set to IBSS"));
10498 return -EINVAL;
10499 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080010500 /* Clearing add IE of beacon */
10501 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
10502 sizeof(tSirMacAddr));
10503 updateIE.smeSessionId = pAdapter->sessionId;
10504 updateIE.ieBufferlength = 0;
10505 updateIE.pAdditionIEBuffer = NULL;
10506 updateIE.append = true;
10507 updateIE.notify = true;
10508 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
10509 &updateIE,
10510 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
10511 hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
10512 }
10513
10514 /* Reset WNI_CFG_PROBE_RSP Flags */
10515 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010516
10517 /* Issue Disconnect request */
10518 INIT_COMPLETION(pAdapter->disconnect_comp_var);
10519 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
10520 pAdapter->sessionId,
10521 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010522 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010523 hddLog(LOGE,
10524 FL("sme_roam_disconnect failed hal_status(%d)"),
10525 hal_status);
10526 return -EAGAIN;
10527 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053010528
10529 /* wait for mc thread to cleanup and then return to upper stack
10530 * so by the time upper layer calls the change interface, we are
10531 * all set to proceed further
10532 */
10533 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
10534 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
10535 if (!rc) {
10536 hdd_err("Failed to disconnect, timed out");
10537 return -ETIMEDOUT;
10538 }
10539
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010540 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010541 return 0;
10542}
10543
10544/**
10545 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
10546 * @wiphy: Pointer to wiphy
10547 * @dev: Pointer to network device
10548 *
10549 * This function is used to leave an IBSS network
10550 *
10551 * Return: 0 for success, non-zero for failure
10552 */
10553static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
10554 struct net_device *dev)
10555{
10556 int ret = 0;
10557
10558 cds_ssr_protect(__func__);
10559 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
10560 cds_ssr_unprotect(__func__);
10561
10562 return ret;
10563}
10564
10565/**
10566 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
10567 * @wiphy: Pointer to wiphy
10568 * @changed: Parameters changed
10569 *
10570 * This function is used to set the phy parameters. RTS Threshold/FRAG
10571 * Threshold/Retry Count etc.
10572 *
10573 * Return: 0 for success, non-zero for failure
10574 */
10575static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
10576 u32 changed)
10577{
10578 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10579 tHalHandle hHal = pHddCtx->hHal;
10580 int status;
10581
10582 ENTER();
10583
Anurag Chouhan6d760662016-02-20 16:05:43 +053010584 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010585 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10586 return -EINVAL;
10587 }
10588
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010589 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010590 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
10591 NO_SESSION, wiphy->rts_threshold));
10592 status = wlan_hdd_validate_context(pHddCtx);
10593
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010594 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010595 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010596
10597 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
10598 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
10599 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
10600
10601 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
10602 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
10603 hddLog(LOGE,
10604 FL("Invalid RTS Threshold value %u"),
10605 rts_threshold);
10606 return -EINVAL;
10607 }
10608
10609 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
10610 rts_threshold)) {
10611 hddLog(LOGE,
10612 FL("sme_cfg_set_int failed for rts_threshold value %u"),
10613 rts_threshold);
10614 return -EIO;
10615 }
10616
10617 hddLog(LOG2, FL("set rts threshold %u"), rts_threshold);
10618 }
10619
10620 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
10621 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
10622 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
10623 wiphy->frag_threshold;
10624
10625 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
10626 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
10627 hddLog(LOGE,
10628 FL("Invalid frag_threshold value %hu"),
10629 frag_threshold);
10630 return -EINVAL;
10631 }
10632
10633 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
10634 frag_threshold)) {
10635 hddLog(LOGE,
10636 FL("sme_cfg_set_int failed for frag_threshold value %hu"),
10637 frag_threshold);
10638 return -EIO;
10639 }
10640
10641 hddLog(LOG2, FL("set frag threshold %hu"), frag_threshold);
10642 }
10643
10644 if ((changed & WIPHY_PARAM_RETRY_SHORT)
10645 || (changed & WIPHY_PARAM_RETRY_LONG)) {
10646 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
10647 wiphy->retry_short : wiphy->retry_long;
10648
10649 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
10650 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
10651 hddLog(LOGE,
10652 FL("Invalid Retry count %hu"), retry_value);
10653 return -EINVAL;
10654 }
10655
10656 if (changed & WIPHY_PARAM_RETRY_SHORT) {
10657 if (0 != sme_cfg_set_int(hHal,
10658 WNI_CFG_LONG_RETRY_LIMIT,
10659 retry_value)) {
10660 hddLog(LOGE,
10661 FL("sme_cfg_set_int failed for long retry count %hu"),
10662 retry_value);
10663 return -EIO;
10664 }
10665 hddLog(LOG2,
10666 FL("set long retry count %hu"), retry_value);
10667 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
10668 if (0 != sme_cfg_set_int(hHal,
10669 WNI_CFG_SHORT_RETRY_LIMIT,
10670 retry_value)) {
10671 hddLog(LOGE,
10672 FL("sme_cfg_set_int failed for short retry count %hu"),
10673 retry_value);
10674 return -EIO;
10675 }
10676 hddLog(LOG2,
10677 FL("set short retry count %hu"), retry_value);
10678 }
10679 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010680 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010681 return 0;
10682}
10683
10684/**
10685 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
10686 * @wiphy: Pointer to wiphy
10687 * @changed: Parameters changed
10688 *
10689 * Return: 0 for success, non-zero for failure
10690 */
10691static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
10692{
10693 int ret;
10694
10695 cds_ssr_protect(__func__);
10696 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
10697 cds_ssr_unprotect(__func__);
10698
10699 return ret;
10700}
10701
10702/**
10703 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
10704 * key
10705 * @wiphy: Pointer to wiphy
10706 * @dev: Pointer to network device
10707 * @key_index: Key index
10708 *
10709 * Return: 0
10710 */
10711static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
10712 struct net_device *netdev,
10713 u8 key_index)
10714{
10715 ENTER();
10716 return 0;
10717}
10718
10719/**
10720 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
10721 * wlan_hdd_set_default_mgmt_key
10722 * @wiphy: pointer to wiphy
10723 * @netdev: pointer to net_device structure
10724 * @key_index: key index
10725 *
10726 * Return: 0 on success, error number on failure
10727 */
10728static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
10729 struct net_device *netdev,
10730 u8 key_index)
10731{
10732 int ret;
10733
10734 cds_ssr_protect(__func__);
10735 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
10736 cds_ssr_unprotect(__func__);
10737
10738 return ret;
10739}
10740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741/**
10742 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
10743 * @wiphy: Pointer to wiphy
10744 * @dev: Pointer to network device
10745 * @params: Pointer to tx queue parameters
10746 *
10747 * Return: 0
10748 */
10749static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
10750 struct net_device *dev,
10751 struct ieee80211_txq_params *params)
10752{
10753 ENTER();
10754 return 0;
10755}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010756
10757/**
10758 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
10759 * @wiphy: pointer to wiphy
10760 * @netdev: pointer to net_device structure
10761 * @params: pointer to ieee80211_txq_params
10762 *
10763 * Return: 0 on success, error number on failure
10764 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010765static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
10766 struct net_device *dev,
10767 struct ieee80211_txq_params *params)
10768{
10769 int ret;
10770
10771 cds_ssr_protect(__func__);
10772 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
10773 cds_ssr_unprotect(__func__);
10774
10775 return ret;
10776}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777
10778/**
10779 * __wlan_hdd_cfg80211_del_station() - delete station v2
10780 * @wiphy: Pointer to wiphy
10781 * @param: Pointer to delete station parameter
10782 *
10783 * Return: 0 for success, non-zero for failure
10784 */
10785static
10786int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10787 struct net_device *dev,
10788 struct tagCsrDelStaParams *pDelStaParams)
10789{
10790 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10791 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010792 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 hdd_hostapd_state_t *hapd_state;
10794 int status;
10795 uint8_t staId;
10796 uint8_t *mac;
10797
10798 ENTER();
10799
Anurag Chouhan6d760662016-02-20 16:05:43 +053010800 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 hddLog(LOGE, FL("Command not allowed in FTM mode"));
10802 return -EINVAL;
10803 }
10804
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010805 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 TRACE_CODE_HDD_CFG80211_DEL_STA,
10807 pAdapter->sessionId, pAdapter->device_mode));
10808
10809 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10810 status = wlan_hdd_validate_context(pHddCtx);
10811
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010812 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010814
10815 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
10816
Krunal Sonib4326f22016-03-10 13:05:51 -080010817 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
10818 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010819
10820 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10821 if (!hapd_state) {
10822 hddLog(LOGE, "%s: Hostapd State is Null", __func__);
10823 return 0;
10824 }
10825
Anurag Chouhanc5548422016-02-24 18:33:27 +053010826 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 uint16_t i;
10828 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
10829 if ((pAdapter->aStaInfo[i].isUsed) &&
10830 (!pAdapter->aStaInfo[i].
10831 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010832 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833 mac,
10834 pAdapter->aStaInfo[i].
10835 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010836 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010837 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
10838 hdd_ipa_wlan_evt(pAdapter,
10839 pAdapter->
10840 aStaInfo[i].
10841 ucSTAId,
10842 WLAN_CLIENT_DISCONNECT,
10843 mac);
10844 }
10845 hddLog(LOG1,
10846 FL("Delete STA with MAC::"
10847 MAC_ADDRESS_STR),
10848 MAC_ADDR_ARRAY(mac));
10849
10850 if (pHddCtx->dev_dfs_cac_status ==
10851 DFS_CAC_IN_PROGRESS)
10852 goto fn_end;
10853
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010854 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 hdd_softap_sta_disassoc(pAdapter,
10856 mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010857 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010858 hdd_softap_sta_deauth(pAdapter,
10859 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010860 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 pAdapter->aStaInfo[i].
10862 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053010863 qdf_status =
10864 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010865 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010867 if (!QDF_IS_STATUS_SUCCESS(
10868 qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869 hddLog(LOGE,
10870 "%s: Deauth wait time expired",
10871 __func__);
10872 }
10873 }
10874 }
10875 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010876 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010878 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010879 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010880 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010881 hddLog(LOG1,
10882 FL("Skip DEL STA as this is not used::"
10883 MAC_ADDRESS_STR),
10884 MAC_ADDR_ARRAY(mac));
10885 return -ENOENT;
10886 }
10887
10888 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
10889 hdd_ipa_wlan_evt(pAdapter, staId,
10890 WLAN_CLIENT_DISCONNECT, mac);
10891 }
10892
10893 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
10894 true) {
10895 hddLog(LOG1,
10896 FL("Skip DEL STA as deauth is in progress::"
10897 MAC_ADDRESS_STR),
10898 MAC_ADDR_ARRAY(mac));
10899 return -ENOENT;
10900 }
10901
10902 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
10903
10904 hddLog(LOG1,
10905 FL("Delete STA with MAC::" MAC_ADDRESS_STR),
10906 MAC_ADDR_ARRAY(mac));
10907
10908 /* Case: SAP in ACS selected DFS ch and client connected
10909 * Now Radar detected. Then if random channel is another
10910 * DFS ch then new CAC is initiated and no TX allowed.
10911 * So do not send any mgmt frames as it will timeout
10912 * during CAC.
10913 */
10914
10915 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
10916 goto fn_end;
10917
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010918 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919 hdd_softap_sta_disassoc(pAdapter, mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010920 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010921 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010922 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923 pAdapter->aStaInfo[staId].isDeauthInProgress =
10924 false;
10925 hddLog(LOG1,
10926 FL("STA removal failed for ::"
10927 MAC_ADDRESS_STR),
10928 MAC_ADDR_ARRAY(mac));
10929 return -ENOENT;
10930 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053010931 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010932 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053010934 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010935 hddLog(LOGE,
10936 "%s: Deauth wait time expired",
10937 __func__);
10938 }
10939 }
10940 }
10941
10942fn_end:
10943 EXIT();
10944 return 0;
10945}
10946
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080010947#if defined(USE_CFG80211_DEL_STA_V2)
10948/**
10949 * wlan_hdd_del_station() - delete station wrapper
10950 * @adapter: pointer to the hdd adapter
10951 *
10952 * Return: None
10953 */
10954void wlan_hdd_del_station(hdd_adapter_t *adapter)
10955{
10956 struct station_del_parameters del_sta;
10957 del_sta.mac = NULL;
10958 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10959 del_sta.reason_code = eCsrForcedDeauthSta;
10960
10961 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
10962 &del_sta);
10963}
10964#else
10965void wlan_hdd_del_station(hdd_adapter_t *adapter)
10966{
10967 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
10968}
10969#endif
10970
10971#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010972/**
10973 * wlan_hdd_cfg80211_del_station() - delete station v2
10974 * @wiphy: Pointer to wiphy
10975 * @param: Pointer to delete station parameter
10976 *
10977 * Return: 0 for success, non-zero for failure
10978 */
10979int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10980 struct net_device *dev,
10981 struct station_del_parameters *param)
10982#else
10983/**
10984 * wlan_hdd_cfg80211_del_station() - delete station
10985 * @wiphy: Pointer to wiphy
10986 * @mac: Pointer to station mac address
10987 *
10988 * Return: 0 for success, non-zero for failure
10989 */
10990#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10991int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10992 struct net_device *dev,
10993 const uint8_t *mac)
10994#else
10995int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
10996 struct net_device *dev,
10997 uint8_t *mac)
10998#endif
10999#endif
11000{
11001 int ret;
11002 struct tagCsrDelStaParams delStaParams;
11003
11004 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080011005#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080011007 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 return -EINVAL;
11009 }
11010 wlansap_populate_del_sta_params(param->mac, param->reason_code,
11011 param->subtype, &delStaParams);
11012#else
11013 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
11014 (SIR_MAC_MGMT_DEAUTH >> 4),
11015 &delStaParams);
11016#endif
11017 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
11018 cds_ssr_unprotect(__func__);
11019
11020 return ret;
11021}
11022
11023/**
11024 * __wlan_hdd_cfg80211_add_station() - add station
11025 * @wiphy: Pointer to wiphy
11026 * @mac: Pointer to station mac address
11027 * @pmksa: Pointer to add station parameter
11028 *
11029 * Return: 0 for success, non-zero for failure
11030 */
11031static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
11032 struct net_device *dev,
11033 const uint8_t *mac,
11034 struct station_parameters *params)
11035{
11036 int status = -EPERM;
11037#ifdef FEATURE_WLAN_TDLS
11038 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11039 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11040 u32 mask, set;
11041
11042 ENTER();
11043
Anurag Chouhan6d760662016-02-20 16:05:43 +053011044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11046 return -EINVAL;
11047 }
11048
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011049 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011050 TRACE_CODE_HDD_CFG80211_ADD_STA,
11051 pAdapter->sessionId, params->listen_interval));
11052
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011053 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011054 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011055
11056 mask = params->sta_flags_mask;
11057
11058 set = params->sta_flags_set;
11059
11060 hddLog(LOG1, FL("mask 0x%x set 0x%x " MAC_ADDRESS_STR), mask, set,
11061 MAC_ADDR_ARRAY(mac));
11062
11063 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
11064 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
11065 status =
11066 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
11067 }
11068 }
11069#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011070 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011071 return status;
11072}
11073
11074/**
11075 * wlan_hdd_cfg80211_add_station() - add station
11076 * @wiphy: Pointer to wiphy
11077 * @mac: Pointer to station mac address
11078 * @pmksa: Pointer to add station parameter
11079 *
11080 * Return: 0 for success, non-zero for failure
11081 */
11082#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11083static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
11084 struct net_device *dev,
11085 const uint8_t *mac,
11086 struct station_parameters *params)
11087#else
11088static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
11089 struct net_device *dev, uint8_t *mac,
11090 struct station_parameters *params)
11091#endif
11092{
11093 int ret;
11094
11095 cds_ssr_protect(__func__);
11096 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
11097 cds_ssr_unprotect(__func__);
11098
11099 return ret;
11100}
11101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011102/**
11103 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
11104 * @wiphy: Pointer to wiphy
11105 * @dev: Pointer to network device
11106 * @pmksa: Pointer to set pmksa parameter
11107 *
11108 * Return: 0 for success, non-zero for failure
11109 */
11110static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
11111 struct net_device *dev,
11112 struct cfg80211_pmksa *pmksa)
11113{
11114 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11115 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11116 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011117 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118 int status;
11119 tPmkidCacheInfo pmk_id;
11120
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011121 ENTER();
11122
Anurag Chouhan6d760662016-02-20 16:05:43 +053011123 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011124 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11125 return -EINVAL;
11126 }
11127
11128 if (!pmksa) {
11129 hddLog(LOGE, FL("pmksa is NULL"));
11130 return -EINVAL;
11131 }
11132
11133 if (!pmksa->bssid || !pmksa->pmkid) {
11134 hddLog(LOGE, FL("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL"),
11135 pmksa->bssid, pmksa->pmkid);
11136 return -EINVAL;
11137 }
11138
11139 hddLog(LOGW, FL("set PMKSA for " MAC_ADDRESS_STR),
11140 MAC_ADDR_ARRAY(pmksa->bssid));
11141
11142 status = wlan_hdd_validate_context(pHddCtx);
11143
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011144 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146
11147 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
11148
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011149 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
11150 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011151
11152 /* Add to the PMKSA ID Cache in CSR */
11153 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
11154 &pmk_id, 1, false);
11155
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011156 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
11158 pAdapter->sessionId, result));
11159
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011160 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011161 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011162}
11163
11164/**
11165 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
11166 * @wiphy: Pointer to wiphy
11167 * @dev: Pointer to network device
11168 * @pmksa: Pointer to set pmksa parameter
11169 *
11170 * Return: 0 for success, non-zero for failure
11171 */
11172static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
11173 struct net_device *dev,
11174 struct cfg80211_pmksa *pmksa)
11175{
11176 int ret;
11177
11178 cds_ssr_protect(__func__);
11179 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
11180 cds_ssr_unprotect(__func__);
11181
11182 return ret;
11183}
11184
11185/**
11186 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
11187 * @wiphy: Pointer to wiphy
11188 * @dev: Pointer to network device
11189 * @pmksa: Pointer to pmksa parameter
11190 *
11191 * Return: 0 for success, non-zero for failure
11192 */
11193static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
11194 struct net_device *dev,
11195 struct cfg80211_pmksa *pmksa)
11196{
11197 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11198 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11199 tHalHandle halHandle;
11200 int status = 0;
11201
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011202 ENTER();
11203
Anurag Chouhan6d760662016-02-20 16:05:43 +053011204 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11206 return -EINVAL;
11207 }
11208
11209 if (!pmksa) {
11210 hddLog(LOGE, FL("pmksa is NULL"));
11211 return -EINVAL;
11212 }
11213
11214 if (!pmksa->bssid) {
11215 hddLog(LOGE, FL("pmksa->bssid is NULL"));
11216 return -EINVAL;
11217 }
11218
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011219 hddLog(QDF_TRACE_LEVEL_DEBUG, FL("Deleting PMKSA for " MAC_ADDRESS_STR),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220 MAC_ADDR_ARRAY(pmksa->bssid));
11221
11222 status = wlan_hdd_validate_context(pHddCtx);
11223
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011224 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226
11227 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
11228
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011229 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053011230 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
11231 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011233 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 sme_roam_del_pmkid_from_cache(halHandle,
11235 pAdapter->sessionId, pmksa->bssid,
11236 false)) {
11237 hddLog(LOGE, FL("Failed to delete PMKSA for " MAC_ADDRESS_STR),
11238 MAC_ADDR_ARRAY(pmksa->bssid));
11239 status = -EINVAL;
11240 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011241 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 return status;
11243}
11244
11245/**
11246 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
11247 * @wiphy: Pointer to wiphy
11248 * @dev: Pointer to network device
11249 * @pmksa: Pointer to pmksa parameter
11250 *
11251 * Return: 0 for success, non-zero for failure
11252 */
11253static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
11254 struct net_device *dev,
11255 struct cfg80211_pmksa *pmksa)
11256{
11257 int ret;
11258
11259 cds_ssr_protect(__func__);
11260 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
11261 cds_ssr_unprotect(__func__);
11262
11263 return ret;
11264
11265}
11266
11267/**
11268 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
11269 * @wiphy: Pointer to wiphy
11270 * @dev: Pointer to network device
11271 *
11272 * Return: 0 for success, non-zero for failure
11273 */
11274static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
11275 struct net_device *dev)
11276{
11277 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11278 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11279 tHalHandle halHandle;
11280 int status = 0;
11281
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011282 ENTER();
11283
Anurag Chouhan6d760662016-02-20 16:05:43 +053011284 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11286 return -EINVAL;
11287 }
11288
11289 hddLog(LOGW, FL("Flushing PMKSA"));
11290
11291 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11292 status = wlan_hdd_validate_context(pHddCtx);
11293
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011294 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011295 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011296
11297 /* Retrieve halHandle */
11298 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
11299
11300 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011301 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
11303 true)) {
11304 hddLog(LOGE, FL("Cannot flush PMKIDCache"));
11305 status = -EINVAL;
11306 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011307 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308 return status;
11309}
11310
11311/**
11312 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
11313 * @wiphy: Pointer to wiphy
11314 * @dev: Pointer to network device
11315 *
11316 * Return: 0 for success, non-zero for failure
11317 */
11318static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
11319 struct net_device *dev)
11320{
11321 int ret;
11322
11323 cds_ssr_protect(__func__);
11324 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
11325 cds_ssr_unprotect(__func__);
11326
11327 return ret;
11328}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080011330#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331/**
11332 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
11333 * @wiphy: Pointer to wiphy
11334 * @dev: Pointer to network device
11335 * @ftie: Pointer to fast transition ie parameter
11336 *
11337 * Return: 0 for success, non-zero for failure
11338 */
11339static int
11340__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
11341 struct net_device *dev,
11342 struct cfg80211_update_ft_ies_params *ftie)
11343{
11344 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
11345 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11346 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11347 int status;
11348
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011349 ENTER();
11350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351 status = wlan_hdd_validate_context(hdd_ctx);
11352 if (status)
11353 return status;
11354
Anurag Chouhan6d760662016-02-20 16:05:43 +053011355 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011356 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11357 return -EINVAL;
11358 }
11359
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011360 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
11362 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
11363 /* Added for debug on reception of Re-assoc Req. */
11364 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
11365 hddLog(LOGE,
11366 FL("Called with Ie of length = %zu when not associated"),
11367 ftie->ie_len);
11368 hddLog(LOGE, FL("Should be Re-assoc Req IEs"));
11369 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 hddLog(LOG1, FL("%s called with Ie of length = %zu"), __func__,
11371 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372
11373 /* Pass the received FT IEs to SME */
11374 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
11375 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011376 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011377 return 0;
11378}
11379
11380/**
11381 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
11382 * @wiphy: Pointer to wiphy
11383 * @dev: Pointer to network device
11384 * @ftie: Pointer to fast transition ie parameter
11385 *
11386 * Return: 0 for success, non-zero for failure
11387 */
11388static int
11389wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
11390 struct net_device *dev,
11391 struct cfg80211_update_ft_ies_params *ftie)
11392{
11393 int ret;
11394
11395 cds_ssr_protect(__func__);
11396 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
11397 cds_ssr_unprotect(__func__);
11398
11399 return ret;
11400}
11401#endif
11402
11403#ifdef WLAN_FEATURE_GTK_OFFLOAD
11404/**
11405 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
11406 * @callbackContext: Callback context
11407 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
11408 *
11409 * Callback rountine called upon receiving response for get offload info
11410 *
11411 * Return: none
11412 */
11413void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
11414 tpSirGtkOffloadGetInfoRspParams
11415 pGtkOffloadGetInfoRsp)
11416{
11417 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
11418 uint8_t tempReplayCounter[8];
11419 hdd_station_ctx_t *pHddStaCtx;
11420
11421 ENTER();
11422
11423 if (NULL == pAdapter) {
11424 hddLog(LOGE, FL("HDD adapter is Null"));
11425 return;
11426 }
11427
11428 if (NULL == pGtkOffloadGetInfoRsp) {
11429 hddLog(LOGE, FL("pGtkOffloadGetInfoRsp is Null"));
11430 return;
11431 }
11432
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011433 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434 hddLog(LOGE, FL("wlan Failed to get replay counter value"));
11435 return;
11436 }
11437
11438 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11439 /* Update replay counter */
11440 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
11441 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
11442
11443 {
11444 /* changing from little to big endian since supplicant
11445 * works on big endian format
11446 */
11447 int i;
11448 uint8_t *p =
11449 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
11450
11451 for (i = 0; i < 8; i++) {
11452 tempReplayCounter[7 - i] = (uint8_t) p[i];
11453 }
11454 }
11455
11456 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080011457 cfg80211_gtk_rekey_notify(pAdapter->dev,
11458 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 tempReplayCounter, GFP_KERNEL);
11460}
11461
11462/**
11463 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
11464 * @wiphy: Pointer to wiphy
11465 * @dev: Pointer to network device
11466 * @data: Pointer to rekey data
11467 *
11468 * This function is used to offload GTK rekeying job to the firmware.
11469 *
11470 * Return: 0 for success, non-zero for failure
11471 */
11472int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
11473 struct net_device *dev,
11474 struct cfg80211_gtk_rekey_data *data)
11475{
11476 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11477 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11478 hdd_station_ctx_t *pHddStaCtx;
11479 tHalHandle hHal;
11480 int result;
11481 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011482 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011483
11484 ENTER();
11485
Anurag Chouhan6d760662016-02-20 16:05:43 +053011486 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11488 return -EINVAL;
11489 }
11490
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011491 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011492 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
11493 pAdapter->sessionId, pAdapter->device_mode));
11494
11495 result = wlan_hdd_validate_context(pHddCtx);
11496
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011497 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011498 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499
11500 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11501 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11502 if (NULL == hHal) {
11503 hddLog(LOGE, FL("HAL context is Null!!!"));
11504 return -EAGAIN;
11505 }
11506
11507 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
11508 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
11509 NL80211_KCK_LEN);
11510 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
11511 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053011512 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080011513 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 {
11515 /* changing from big to little endian since driver
11516 * works on little endian format
11517 */
11518 uint8_t *p =
11519 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
11520 ullKeyReplayCounter;
11521 int i;
11522
11523 for (i = 0; i < 8; i++) {
11524 p[7 - i] = data->replay_ctr[i];
11525 }
11526 }
11527
11528 if (true == pHddCtx->hdd_wlan_suspended) {
11529 /* if wlan is suspended, enable GTK offload directly from here */
11530 memcpy(&hddGtkOffloadReqParams,
11531 &pHddStaCtx->gtkOffloadReqParams,
11532 sizeof(tSirGtkOffloadParams));
11533 status =
11534 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
11535 pAdapter->sessionId);
11536
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011537 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 hddLog(LOGE, FL("sme_set_gtk_offload failed, status(%d)"),
11539 status);
11540 return -EINVAL;
11541 }
11542 hddLog(LOG1, FL("sme_set_gtk_offload successful"));
11543 } else {
11544 hddLog(LOG1,
11545 FL("wlan not suspended GTKOffload request is stored"));
11546 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011547 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011548 return result;
11549}
11550
11551/**
11552 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
11553 * @wiphy: Pointer to wiphy
11554 * @dev: Pointer to network device
11555 * @data: Pointer to rekey data
11556 *
11557 * This function is used to offload GTK rekeying job to the firmware.
11558 *
11559 * Return: 0 for success, non-zero for failure
11560 */
11561int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
11562 struct net_device *dev,
11563 struct cfg80211_gtk_rekey_data *data)
11564{
11565 int ret;
11566
11567 cds_ssr_protect(__func__);
11568 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
11569 cds_ssr_unprotect(__func__);
11570
11571 return ret;
11572}
11573#endif /*WLAN_FEATURE_GTK_OFFLOAD */
11574
11575/**
11576 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
11577 * @wiphy: Pointer to wiphy
11578 * @dev: Pointer to network device
11579 * @param: Pointer to access control parameter
11580 *
11581 * Return: 0 for success, non-zero for failure
11582 */
11583static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
11584 struct net_device *dev,
11585 const struct cfg80211_acl_data *params)
11586{
11587 int i;
11588 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11589 hdd_hostapd_state_t *pHostapdState;
11590 tsap_Config_t *pConfig;
11591 v_CONTEXT_t p_cds_context = NULL;
11592 hdd_context_t *pHddCtx;
11593 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011594 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011595
11596 ENTER();
11597
Anurag Chouhan6d760662016-02-20 16:05:43 +053011598 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11600 return -EINVAL;
11601 }
11602
11603 if (NULL == params) {
11604 hddLog(LOGE, FL("params is Null"));
11605 return -EINVAL;
11606 }
11607
11608 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11609 status = wlan_hdd_validate_context(pHddCtx);
11610
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011611 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011613
11614 p_cds_context = pHddCtx->pcds_context;
11615 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11616
11617 if (NULL == pHostapdState) {
11618 hddLog(LOGE, FL("pHostapdState is Null"));
11619 return -EINVAL;
11620 }
11621
11622 hddLog(LOGE, "acl policy: = %d no acl entries = %d", params->acl_policy,
11623 params->n_acl_entries);
11624
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011625 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053011626 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
11627 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080011628 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011629 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
11630
11631 /* default value */
11632 pConfig->num_accept_mac = 0;
11633 pConfig->num_deny_mac = 0;
11634
11635 /**
11636 * access control policy
11637 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
11638 * listed in hostapd.deny file.
11639 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
11640 * listed in hostapd.accept file.
11641 */
11642 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
11643 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
11644 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
11645 params->acl_policy) {
11646 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
11647 } else {
11648 hddLog(LOGE, FL("Acl Policy : %d is not supported"),
11649 params->acl_policy);
11650 return -ENOTSUPP;
11651 }
11652
11653 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
11654 pConfig->num_accept_mac = params->n_acl_entries;
11655 for (i = 0; i < params->n_acl_entries; i++) {
11656 hddLog(LOG1,
11657 FL("** Add ACL MAC entry %i in WhiletList :"
11658 MAC_ADDRESS_STR), i,
11659 MAC_ADDR_ARRAY(
11660 params->mac_addrs[i].addr));
11661
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011662 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663 params->mac_addrs[i].addr,
11664 sizeof(qcmacaddr));
11665 }
11666 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
11667 pConfig->num_deny_mac = params->n_acl_entries;
11668 for (i = 0; i < params->n_acl_entries; i++) {
11669 hddLog(LOG1,
11670 FL("** Add ACL MAC entry %i in BlackList :"
11671 MAC_ADDRESS_STR), i,
11672 MAC_ADDR_ARRAY(
11673 params->mac_addrs[i].addr));
11674
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011675 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011676 params->mac_addrs[i].addr,
11677 sizeof(qcmacaddr));
11678 }
11679 }
11680#ifdef WLAN_FEATURE_MBSSID
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011681 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 wlansap_set_mac_acl(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
11683 pConfig);
11684#else
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011685 qdf_status = wlansap_set_mac_acl(p_cds_context, pConfig);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686#endif
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011687 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688 hddLog(LOGE, FL("SAP Set Mac Acl fail"));
11689 return -EINVAL;
11690 }
11691 } else {
11692 hddLog(LOG1, FL("Invalid device_mode %s(%d)"),
11693 hdd_device_mode_to_string(pAdapter->device_mode),
11694 pAdapter->device_mode);
11695 return -EINVAL;
11696 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011697 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698 return 0;
11699}
11700
11701/**
11702 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
11703 * __wlan_hdd_cfg80211_set_mac_acl
11704 * @wiphy: pointer to wiphy structure
11705 * @dev: pointer to net_device
11706 * @params: pointer to cfg80211_acl_data
11707 *
11708 * Return; 0 on success, error number otherwise
11709 */
11710static int
11711wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
11712 struct net_device *dev,
11713 const struct cfg80211_acl_data *params)
11714{
11715 int ret;
11716
11717 cds_ssr_protect(__func__);
11718 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
11719 cds_ssr_unprotect(__func__);
11720
11721 return ret;
11722}
11723
11724#ifdef WLAN_NL80211_TESTMODE
11725#ifdef FEATURE_WLAN_LPHB
11726/**
11727 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
11728 * @pHddCtx: Pointer to hdd context
11729 * @lphbInd: Pointer to low power heart beat indication parameter
11730 *
11731 * Return: none
11732 */
11733void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
11734{
11735 struct sk_buff *skb;
11736
11737 hddLog(LOGE, FL("LPHB indication arrived"));
11738
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011739 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741
11742 if (NULL == lphbInd) {
11743 hddLog(LOGE, FL("invalid argument lphbInd"));
11744 return;
11745 }
11746
11747 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
11748 wiphy, sizeof(tSirLPHBInd),
11749 GFP_ATOMIC);
11750 if (!skb) {
11751 hddLog(LOGE, FL("LPHB timeout, NL buffer alloc fail"));
11752 return;
11753 }
11754
11755 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
11756 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_CMD put fail"));
11757 goto nla_put_failure;
11758 }
11759 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
11760 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_TYPE put fail"));
11761 goto nla_put_failure;
11762 }
11763 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
11764 hddLog(LOGE, FL("WLAN_HDD_TM_ATTR_DATA put fail"));
11765 goto nla_put_failure;
11766 }
11767 cfg80211_testmode_event(skb, GFP_ATOMIC);
11768 return;
11769
11770nla_put_failure:
11771 hddLog(LOGE, FL("NLA Put fail"));
11772 kfree_skb(skb);
11773
11774 return;
11775}
11776#endif /* FEATURE_WLAN_LPHB */
11777
11778/**
11779 * __wlan_hdd_cfg80211_testmode() - test mode
11780 * @wiphy: Pointer to wiphy
11781 * @data: Data pointer
11782 * @len: Data length
11783 *
11784 * Return: 0 for success, non-zero for failure
11785 */
11786static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
11787 void *data, int len)
11788{
11789 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
11790 int err;
11791 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11792
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011793 ENTER();
11794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795 err = wlan_hdd_validate_context(pHddCtx);
11796 if (err)
11797 return err;
11798
11799 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
11800 len, wlan_hdd_tm_policy);
11801 if (err) {
11802 hddLog(LOGE, FL("Testmode INV ATTR"));
11803 return err;
11804 }
11805
11806 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
11807 hddLog(LOGE, FL("Testmode INV CMD"));
11808 return -EINVAL;
11809 }
11810
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011811 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053011812 TRACE_CODE_HDD_CFG80211_TESTMODE,
11813 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011814 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
11815#ifdef FEATURE_WLAN_LPHB
11816 /* Low Power Heartbeat configuration request */
11817 case WLAN_HDD_TM_CMD_WLAN_HB:
11818 {
11819 int buf_len;
11820 void *buf;
11821 tSirLPHBReq *hb_params = NULL;
11822 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011823 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011824
11825 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
11826 hddLog(LOGE, FL("Testmode INV DATA"));
11827 return -EINVAL;
11828 }
11829
11830 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
11831 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
11832
11833 hb_params_temp = (tSirLPHBReq *) buf;
11834 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
11835 && (hb_params_temp->params.lphbTcpParamReq.
11836 timePeriodSec == 0))
11837 return -EINVAL;
11838
11839 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011840 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 if (NULL == hb_params) {
11842 hddLog(LOGE, FL("Request Buffer Alloc Fail"));
11843 return -ENOMEM;
11844 }
11845
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011846 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011847 smeStatus =
11848 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
11849 hb_params,
11850 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011851 if (QDF_STATUS_SUCCESS != smeStatus) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011852 hddLog(LOGE, "LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011853 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011854 }
11855 return 0;
11856 }
11857#endif /* FEATURE_WLAN_LPHB */
11858
11859#if defined(QCA_WIFI_FTM)
11860 case WLAN_HDD_TM_CMD_WLAN_FTM:
11861 {
11862 int buf_len;
11863 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011864 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070011866 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867 return -EINVAL;
11868 }
11869
11870 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
11871 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
11872
Ryan Hsucfef0ae2016-04-28 10:20:46 -070011873 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011874
11875 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
11876
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011877 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878 err = -EBUSY;
11879 break;
11880 }
11881#endif
11882
11883 default:
11884 hddLog(LOGE, FL("command %d not supported"),
11885 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
11886 return -EOPNOTSUPP;
11887 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011888 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 return err;
11890}
11891
11892/**
11893 * wlan_hdd_cfg80211_testmode() - test mode
11894 * @wiphy: Pointer to wiphy
11895 * @dev: Pointer to network device
11896 * @data: Data pointer
11897 * @len: Data length
11898 *
11899 * Return: 0 for success, non-zero for failure
11900 */
11901static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
11902#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11903 struct wireless_dev *wdev,
11904#endif
11905 void *data, int len)
11906{
11907 int ret;
11908
11909 cds_ssr_protect(__func__);
11910 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
11911 cds_ssr_unprotect(__func__);
11912
11913 return ret;
11914}
11915
11916#if defined(QCA_WIFI_FTM)
11917/**
11918 * wlan_hdd_testmode_rx_event() - test mode rx event handler
11919 * @buf: Pointer to buffer
11920 * @buf_len: Buffer length
11921 *
11922 * Return: none
11923 */
11924void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
11925{
11926 struct sk_buff *skb;
11927 hdd_context_t *hdd_ctx;
11928
11929 if (!buf || !buf_len) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011930 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 "%s: buf or buf_len invalid, buf = %p buf_len = %zu",
11932 __func__, buf, buf_len);
11933 return;
11934 }
11935
Anurag Chouhan6d760662016-02-20 16:05:43 +053011936 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011937 if (!hdd_ctx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011938 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011939 "%s: hdd context invalid", __func__);
11940 return;
11941 }
11942
11943 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
11944 buf_len, GFP_KERNEL);
11945 if (!skb) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011946 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 "%s: failed to allocate testmode rx skb!", __func__);
11948 return;
11949 }
11950
11951 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
11952 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
11953 goto nla_put_failure;
11954
Ryan Hsucfef0ae2016-04-28 10:20:46 -070011955 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011956
11957 cfg80211_testmode_event(skb, GFP_KERNEL);
11958 return;
11959
11960nla_put_failure:
11961 kfree_skb(skb);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011962 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011963 "%s: nla_put failed on testmode rx skb!", __func__);
11964}
11965#endif
11966#endif /* CONFIG_NL80211_TESTMODE */
11967
11968#ifdef QCA_HT_2040_COEX
11969/**
11970 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
11971 * @wiphy: Pointer to wiphy
11972 * @dev: Pointer to network device
11973 * @chandef: Pointer to channel definition parameter
11974 *
11975 * Return: 0 for success, non-zero for failure
11976 */
11977static int
11978__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
11979 struct net_device *dev,
11980 struct cfg80211_chan_def *chandef)
11981{
11982 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11983 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011984 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011985 tSmeConfigParams sme_config;
11986 bool cbModeChange;
11987
Anurag Chouhan6d760662016-02-20 16:05:43 +053011988 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011989 hddLog(LOGE, FL("Command not allowed in FTM mode"));
11990 return -EINVAL;
11991 }
11992
11993 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11994 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011995 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011998 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011999 sme_get_config_param(pHddCtx->hHal, &sme_config);
12000 switch (chandef->width) {
12001 case NL80211_CHAN_WIDTH_20:
12002 if (sme_config.csrConfig.channelBondingMode24GHz !=
12003 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
12004 sme_config.csrConfig.channelBondingMode24GHz =
12005 eCSR_INI_SINGLE_CHANNEL_CENTERED;
12006 sme_update_config(pHddCtx->hHal, &sme_config);
12007 cbModeChange = true;
12008 }
12009 break;
12010
12011 case NL80211_CHAN_WIDTH_40:
12012 if (sme_config.csrConfig.channelBondingMode24GHz ==
12013 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
12014 if (NL80211_CHAN_HT40MINUS ==
12015 cfg80211_get_chandef_type(chandef))
12016 sme_config.csrConfig.channelBondingMode24GHz =
12017 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
12018 else
12019 sme_config.csrConfig.channelBondingMode24GHz =
12020 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
12021 sme_update_config(pHddCtx->hHal, &sme_config);
12022 cbModeChange = true;
12023 }
12024 break;
12025
12026 default:
12027 hddLog(LOGE, FL("Error!!! Invalid HT20/40 mode !"));
12028 return -EINVAL;
12029 }
12030
12031 if (!cbModeChange)
12032 return 0;
12033
Krunal Sonib4326f22016-03-10 13:05:51 -080012034 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012035 return 0;
12036
12037 hddLog(LOG1, FL("Channel bonding changed to %d"),
12038 sme_config.csrConfig.channelBondingMode24GHz);
12039
12040 /* Change SAP ht2040 mode */
12041 status = hdd_set_sap_ht2040_mode(pAdapter,
12042 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012043 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012044 hddLog(LOGE, FL("Error!!! Cannot set SAP HT20/40 mode!"));
12045 return -EINVAL;
12046 }
12047
12048 return 0;
12049}
12050
12051/**
12052 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
12053 * @wiphy: Pointer to wiphy
12054 * @dev: Pointer to network device
12055 * @chandef: Pointer to channel definition parameter
12056 *
12057 * Return: 0 for success, non-zero for failure
12058 */
12059static int
12060wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
12061 struct net_device *dev,
12062 struct cfg80211_chan_def *chandef)
12063{
12064 int ret;
12065
12066 cds_ssr_protect(__func__);
12067 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
12068 cds_ssr_unprotect(__func__);
12069
12070 return ret;
12071}
12072#endif
12073
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012074#ifdef CHANNEL_SWITCH_SUPPORTED
12075/**
12076 * __wlan_hdd_cfg80211_channel_switch()- function to switch
12077 * channel in SAP/GO
12078 * @wiphy: wiphy pointer
12079 * @dev: dev pointer.
12080 * @csa_params: Change channel params
12081 *
12082 * This function is called to switch channel in SAP/GO
12083 *
12084 * Return: 0 if success else return non zero
12085 */
12086static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
12087 struct net_device *dev,
12088 struct cfg80211_csa_settings *csa_params)
12089{
12090 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12091 hdd_context_t *hdd_ctx;
12092 uint8_t channel;
12093 uint16_t freq;
12094 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080012095 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012096
12097 hddLog(LOG1, FL("Set Freq %d"),
12098 csa_params->chandef.chan->center_freq);
12099
12100 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
12101 ret = wlan_hdd_validate_context(hdd_ctx);
12102
12103 if (0 != ret)
12104 return ret;
12105
Krunal Sonib4326f22016-03-10 13:05:51 -080012106 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
12107 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012108 return -ENOTSUPP;
12109
12110 freq = csa_params->chandef.chan->center_freq;
12111 channel = cds_freq_to_chan(freq);
12112
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053012113 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
12114
12115 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012116 return ret;
12117}
12118
12119/**
12120 * wlan_hdd_cfg80211_channel_switch()- function to switch
12121 * channel in SAP/GO
12122 * @wiphy: wiphy pointer
12123 * @dev: dev pointer.
12124 * @csa_params: Change channel params
12125 *
12126 * This function is called to switch channel in SAP/GO
12127 *
12128 * Return: 0 if success else return non zero
12129 */
12130static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
12131 struct net_device *dev,
12132 struct cfg80211_csa_settings *csa_params)
12133{
12134 int ret;
12135
12136 cds_ssr_protect(__func__);
12137 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
12138 cds_ssr_unprotect(__func__);
12139 return ret;
12140}
12141#endif
12142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143/**
12144 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
12145 * translation from NL to policy manager type
12146 * @type: Generic connection mode type defined in NL
12147 *
12148 *
12149 * This function provides the type translation
12150 *
12151 * Return: cds_con_mode enum
12152 */
12153enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
12154 enum nl80211_iftype type)
12155{
12156 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
12157 switch (type) {
12158 case NL80211_IFTYPE_STATION:
12159 mode = CDS_STA_MODE;
12160 break;
12161 case NL80211_IFTYPE_P2P_CLIENT:
12162 mode = CDS_P2P_CLIENT_MODE;
12163 break;
12164 case NL80211_IFTYPE_P2P_GO:
12165 mode = CDS_P2P_GO_MODE;
12166 break;
12167 case NL80211_IFTYPE_AP:
12168 mode = CDS_SAP_MODE;
12169 break;
12170 case NL80211_IFTYPE_ADHOC:
12171 mode = CDS_IBSS_MODE;
12172 break;
12173 default:
12174 hddLog(LOGE, FL("Unsupported interface type (%d)"),
12175 type);
12176 }
12177 return mode;
12178}
12179
12180/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012181 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
12182 * @wiphy: Handle to struct wiphy to get handle to module context.
12183 * @chandef: Contains information about the capture channel to be set.
12184 *
12185 * This interface is called if and only if monitor mode interface alone is
12186 * active.
12187 *
12188 * Return: 0 success or error code on failure.
12189 */
12190static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
12191 struct cfg80211_chan_def *chandef)
12192{
12193 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
12194 hdd_adapter_t *adapter;
12195 hdd_station_ctx_t *sta_ctx;
12196 struct hdd_mon_set_ch_info *ch_info;
12197 QDF_STATUS status;
12198 tHalHandle hal_hdl;
12199 struct qdf_mac_addr bssid;
12200 tCsrRoamProfile roam_profile;
12201 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012202 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012203 int ret;
12204 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
12205
12206 ENTER();
12207
12208 ret = wlan_hdd_validate_context(hdd_ctx);
12209 if (ret)
12210 return ret;
12211
12212 hal_hdl = hdd_ctx->hHal;
12213
12214 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
12215 if (!adapter)
12216 return -EIO;
12217
12218 hdd_info("%s: set monitor mode Channel %d and freq %d",
12219 adapter->dev->name, chan_num, chandef->chan->center_freq);
12220
12221 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
12222 ch_info = &sta_ctx->ch_info;
12223 hdd_select_cbmode(adapter, chan_num);
12224 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
12225 roam_profile.ChannelInfo.numOfChannels = 1;
12226 roam_profile.phyMode = ch_info->phy_mode;
12227 roam_profile.ch_params.ch_width = chandef->width;
12228
12229 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
12230 QDF_MAC_ADDR_SIZE);
12231
12232 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012233 /*
12234 * CDS api expects secondary channel for calculating
12235 * the channel params
12236 */
12237 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
12238 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
12239 if (chan_num >= 1 && chan_num <= 5)
12240 sec_ch = chan_num + 4;
12241 else if (chan_num >= 6 && chan_num <= 13)
12242 sec_ch = chan_num - 4;
12243 }
12244 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012245 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
12246 &roam_profile);
12247 if (status) {
12248 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
12249 status);
12250 ret = qdf_status_to_os_return(status);
12251 return ret;
12252 }
12253 EXIT();
12254 return 0;
12255}
12256
12257/**
12258 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
12259 * @wiphy: Handle to struct wiphy to get handle to module context.
12260 * @chandef: Contains information about the capture channel to be set.
12261 *
12262 * This interface is called if and only if monitor mode interface alone is
12263 * active.
12264 *
12265 * Return: 0 success or error code on failure.
12266 */
12267static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
12268 struct cfg80211_chan_def *chandef)
12269{
12270 int ret;
12271
12272 cds_ssr_protect(__func__);
12273 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
12274 cds_ssr_unprotect(__func__);
12275 return ret;
12276}
12277
12278/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012279 * struct cfg80211_ops - cfg80211_ops
12280 *
12281 * @add_virtual_intf: Add virtual interface
12282 * @del_virtual_intf: Delete virtual interface
12283 * @change_virtual_intf: Change virtual interface
12284 * @change_station: Change station
12285 * @add_beacon: Add beacon in sap mode
12286 * @del_beacon: Delete beacon in sap mode
12287 * @set_beacon: Set beacon in sap mode
12288 * @start_ap: Start ap
12289 * @change_beacon: Change beacon
12290 * @stop_ap: Stop ap
12291 * @change_bss: Change bss
12292 * @add_key: Add key
12293 * @get_key: Get key
12294 * @del_key: Delete key
12295 * @set_default_key: Set default key
12296 * @set_channel: Set channel
12297 * @scan: Scan
12298 * @connect: Connect
12299 * @disconnect: Disconnect
12300 * @join_ibss = Join ibss
12301 * @leave_ibss = Leave ibss
12302 * @set_wiphy_params = Set wiphy params
12303 * @set_tx_power = Set tx power
12304 * @get_tx_power = get tx power
12305 * @remain_on_channel = Remain on channel
12306 * @cancel_remain_on_channel = Cancel remain on channel
12307 * @mgmt_tx = Tx management frame
12308 * @mgmt_tx_cancel_wait = Cancel management tx wait
12309 * @set_default_mgmt_key = Set default management key
12310 * @set_txq_params = Set tx queue parameters
12311 * @get_station = Get station
12312 * @set_power_mgmt = Set power management
12313 * @del_station = Delete station
12314 * @add_station = Add station
12315 * @set_pmksa = Set pmksa
12316 * @del_pmksa = Delete pmksa
12317 * @flush_pmksa = Flush pmksa
12318 * @update_ft_ies = Update FT IEs
12319 * @tdls_mgmt = Tdls management
12320 * @tdls_oper = Tdls operation
12321 * @set_rekey_data = Set rekey data
12322 * @sched_scan_start = Scheduled scan start
12323 * @sched_scan_stop = Scheduled scan stop
12324 * @resume = Resume wlan
12325 * @suspend = Suspend wlan
12326 * @set_mac_acl = Set mac acl
12327 * @testmode_cmd = Test mode command
12328 * @set_ap_chanwidth = Set AP channel bandwidth
12329 * @dump_survey = Dump survey
12330 * @key_mgmt_set_pmk = Set pmk key management
12331 */
12332static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
12333 .add_virtual_intf = wlan_hdd_add_virtual_intf,
12334 .del_virtual_intf = wlan_hdd_del_virtual_intf,
12335 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
12336 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012337 .start_ap = wlan_hdd_cfg80211_start_ap,
12338 .change_beacon = wlan_hdd_cfg80211_change_beacon,
12339 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340 .change_bss = wlan_hdd_cfg80211_change_bss,
12341 .add_key = wlan_hdd_cfg80211_add_key,
12342 .get_key = wlan_hdd_cfg80211_get_key,
12343 .del_key = wlan_hdd_cfg80211_del_key,
12344 .set_default_key = wlan_hdd_cfg80211_set_default_key,
12345 .scan = wlan_hdd_cfg80211_scan,
12346 .connect = wlan_hdd_cfg80211_connect,
12347 .disconnect = wlan_hdd_cfg80211_disconnect,
12348 .join_ibss = wlan_hdd_cfg80211_join_ibss,
12349 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
12350 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
12351 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
12352 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
12353 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
12354 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
12355 .mgmt_tx = wlan_hdd_mgmt_tx,
12356 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
12357 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
12358 .set_txq_params = wlan_hdd_set_txq_params,
12359 .get_station = wlan_hdd_cfg80211_get_station,
12360 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
12361 .del_station = wlan_hdd_cfg80211_del_station,
12362 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
12364 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
12365 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080012366#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012367 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
12368#endif
12369#ifdef FEATURE_WLAN_TDLS
12370 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
12371 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
12372#endif
12373#ifdef WLAN_FEATURE_GTK_OFFLOAD
12374 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
12375#endif /* WLAN_FEATURE_GTK_OFFLOAD */
12376#ifdef FEATURE_WLAN_SCAN_PNO
12377 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
12378 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
12379#endif /*FEATURE_WLAN_SCAN_PNO */
12380 .resume = wlan_hdd_cfg80211_resume_wlan,
12381 .suspend = wlan_hdd_cfg80211_suspend_wlan,
12382 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
12383#ifdef WLAN_NL80211_TESTMODE
12384 .testmode_cmd = wlan_hdd_cfg80211_testmode,
12385#endif
12386#ifdef QCA_HT_2040_COEX
12387 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
12388#endif
12389 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053012390#ifdef CHANNEL_SWITCH_SUPPORTED
12391 .channel_switch = wlan_hdd_cfg80211_channel_switch,
12392#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012393 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053012394#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
12395 defined(CFG80211_ABORT_SCAN)
12396 .abort_scan = wlan_hdd_cfg80211_abort_scan,
12397#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012398};