blob: 01c4eca68398d17e62985dd530dd1b2a7200b316 [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
Jeff Johnson9c50e782016-06-29 15:28:56 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/etherdevice.h>
43#include <linux/wireless.h>
44#include <wlan_hdd_includes.h>
45#include <net/arp.h>
46#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053047#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include <wlan_hdd_wowl.h>
49#include <ani_global.h>
50#include "sir_params.h"
51#include "dot11f.h"
52#include "wlan_hdd_assoc.h"
53#include "wlan_hdd_wext.h"
54#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070055#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "wlan_hdd_softap_tx_rx.h"
60#include "wlan_hdd_main.h"
61#include "wlan_hdd_power.h"
62#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "cds_utils.h"
66#include "cds_sched.h"
67#include "wlan_hdd_scan.h"
68#include <qc_sap_ioctl.h>
69#include "wlan_hdd_tdls.h"
70#include "wlan_hdd_wmm.h"
71#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053072#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073#include "wlan_hdd_misc.h"
74#include "wlan_hdd_nan.h"
75#include <wlan_hdd_ipa.h>
76#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053078#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053079#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070095#include "ol_txrx.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053098#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070099#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700100#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530101#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#define g_mode_rates_size (12)
104#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
106 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
107
108/*
109 * Android CTS verifier needs atleast this much wait time (in msec)
110 */
111#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
112
113/*
114 * Refer @tCfgProtection structure for definition of the bit map.
115 * below value is obtained by setting the following bit-fields.
116 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
117 */
118#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
119
120#define HDD2GHZCHAN(freq, chan, flag) { \
121 .band = IEEE80211_BAND_2GHZ, \
122 .center_freq = (freq), \
123 .hw_value = (chan), \
124 .flags = (flag), \
125 .max_antenna_gain = 0, \
126 .max_power = 30, \
127}
128
129#define HDD5GHZCHAN(freq, chan, flag) { \
130 .band = IEEE80211_BAND_5GHZ, \
131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
139 { \
140 .bitrate = rate, \
141 .hw_value = rate_id, \
142 .flags = flag, \
143 }
144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
146#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147
148#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
Agrawal Ashish65634612016-08-18 13:24:32 +0530150#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
151 mode <= DFS_MODE_DEPRIORITIZE))
152#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
153 || (channel >= 36 && channel <= 184))
154
Peng Xu4d67c8f2015-10-16 16:02:26 -0700155#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530156#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158static const u32 hdd_cipher_suites[] = {
159 WLAN_CIPHER_SUITE_WEP40,
160 WLAN_CIPHER_SUITE_WEP104,
161 WLAN_CIPHER_SUITE_TKIP,
162#ifdef FEATURE_WLAN_ESE
163#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
164#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
165 WLAN_CIPHER_SUITE_BTK,
166 WLAN_CIPHER_SUITE_KRK,
167 WLAN_CIPHER_SUITE_CCMP,
168#else
169 WLAN_CIPHER_SUITE_CCMP,
170#endif
171#ifdef FEATURE_WLAN_WAPI
172 WLAN_CIPHER_SUITE_SMS4,
173#endif
174#ifdef WLAN_FEATURE_11W
175 WLAN_CIPHER_SUITE_AES_CMAC,
176#endif
177};
178
Abhishek Singhf512bf32016-05-04 16:47:46 +0530179static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2417, 2, 0),
182 HDD2GHZCHAN(2422, 3, 0),
183 HDD2GHZCHAN(2427, 4, 0),
184 HDD2GHZCHAN(2432, 5, 0),
185 HDD2GHZCHAN(2437, 6, 0),
186 HDD2GHZCHAN(2442, 7, 0),
187 HDD2GHZCHAN(2447, 8, 0),
188 HDD2GHZCHAN(2452, 9, 0),
189 HDD2GHZCHAN(2457, 10, 0),
190 HDD2GHZCHAN(2462, 11, 0),
191 HDD2GHZCHAN(2467, 12, 0),
192 HDD2GHZCHAN(2472, 13, 0),
193 HDD2GHZCHAN(2484, 14, 0),
194};
195
Abhishek Singhf512bf32016-05-04 16:47:46 +0530196static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 HDD5GHZCHAN(5180, 36, 0),
198 HDD5GHZCHAN(5200, 40, 0),
199 HDD5GHZCHAN(5220, 44, 0),
200 HDD5GHZCHAN(5240, 48, 0),
201 HDD5GHZCHAN(5260, 52, 0),
202 HDD5GHZCHAN(5280, 56, 0),
203 HDD5GHZCHAN(5300, 60, 0),
204 HDD5GHZCHAN(5320, 64, 0),
205 HDD5GHZCHAN(5500, 100, 0),
206 HDD5GHZCHAN(5520, 104, 0),
207 HDD5GHZCHAN(5540, 108, 0),
208 HDD5GHZCHAN(5560, 112, 0),
209 HDD5GHZCHAN(5580, 116, 0),
210 HDD5GHZCHAN(5600, 120, 0),
211 HDD5GHZCHAN(5620, 124, 0),
212 HDD5GHZCHAN(5640, 128, 0),
213 HDD5GHZCHAN(5660, 132, 0),
214 HDD5GHZCHAN(5680, 136, 0),
215 HDD5GHZCHAN(5700, 140, 0),
216 HDD5GHZCHAN(5720, 144, 0),
217 HDD5GHZCHAN(5745, 149, 0),
218 HDD5GHZCHAN(5765, 153, 0),
219 HDD5GHZCHAN(5785, 157, 0),
220 HDD5GHZCHAN(5805, 161, 0),
221 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 HDD5GHZCHAN(5852, 170, 0),
223 HDD5GHZCHAN(5855, 171, 0),
224 HDD5GHZCHAN(5860, 172, 0),
225 HDD5GHZCHAN(5865, 173, 0),
226 HDD5GHZCHAN(5870, 174, 0),
227 HDD5GHZCHAN(5875, 175, 0),
228 HDD5GHZCHAN(5880, 176, 0),
229 HDD5GHZCHAN(5885, 177, 0),
230 HDD5GHZCHAN(5890, 178, 0),
231 HDD5GHZCHAN(5895, 179, 0),
232 HDD5GHZCHAN(5900, 180, 0),
233 HDD5GHZCHAN(5905, 181, 0),
234 HDD5GHZCHAN(5910, 182, 0),
235 HDD5GHZCHAN(5915, 183, 0),
236 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237};
238
239static struct ieee80211_rate g_mode_rates[] = {
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] = {
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530266 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
268 .band = IEEE80211_BAND_2GHZ,
269 .bitrates = g_mode_rates,
270 .n_bitrates = g_mode_rates_size,
271 .ht_cap.ht_supported = 1,
272 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
273 | IEEE80211_HT_CAP_GRN_FLD
274 | IEEE80211_HT_CAP_DSSSCCK40
275 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
276 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
277 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
278 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
279 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
280 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
281 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
282};
283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530285 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
287 .band = IEEE80211_BAND_5GHZ,
288 .bitrates = a_mode_rates,
289 .n_bitrates = a_mode_rates_size,
290 .ht_cap.ht_supported = 1,
291 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
292 | IEEE80211_HT_CAP_GRN_FLD
293 | IEEE80211_HT_CAP_DSSSCCK40
294 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
295 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
296 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
297 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
298 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
299 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
300 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
301 .vht_cap.vht_supported = 1,
302};
303
304/* This structure contain information what kind of frame are expected in
305 TX/RX direction for each kind of interface */
306static const struct ieee80211_txrx_stypes
307 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
308 [NL80211_IFTYPE_STATION] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ACTION) |
311 BIT(SIR_MAC_MGMT_PROBE_REQ),
312 },
313 [NL80211_IFTYPE_AP] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
316 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ) |
318 BIT(SIR_MAC_MGMT_DISASSOC) |
319 BIT(SIR_MAC_MGMT_AUTH) |
320 BIT(SIR_MAC_MGMT_DEAUTH) |
321 BIT(SIR_MAC_MGMT_ACTION),
322 },
323 [NL80211_IFTYPE_ADHOC] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_P2P_CLIENT] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ACTION) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ),
337 },
338 [NL80211_IFTYPE_P2P_GO] = {
339 /* This is also same as for SoftAP */
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ) |
344 BIT(SIR_MAC_MGMT_DISASSOC) |
345 BIT(SIR_MAC_MGMT_AUTH) |
346 BIT(SIR_MAC_MGMT_DEAUTH) |
347 BIT(SIR_MAC_MGMT_ACTION),
348 },
349};
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351/* Interface limits and combinations registered by the driver */
352
353/* STA ( + STA ) combination */
354static const struct ieee80211_iface_limit
355 wlan_hdd_sta_iface_limit[] = {
356 {
357 .max = 3, /* p2p0 is a STA as well */
358 .types = BIT(NL80211_IFTYPE_STATION),
359 },
360};
361
362/* ADHOC (IBSS) limit */
363static const struct ieee80211_iface_limit
364 wlan_hdd_adhoc_iface_limit[] = {
365 {
366 .max = 1,
367 .types = BIT(NL80211_IFTYPE_STATION),
368 },
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_ADHOC),
372 },
373};
374
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
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 wlan_hdd_iface_combination[] = {
496 /* STA */
497 {
498 .limits = wlan_hdd_sta_iface_limit,
499 .num_different_channels = 2,
500 .max_interfaces = 3,
501 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
502 },
503 /* ADHOC */
504 {
505 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700506 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 .max_interfaces = 2,
508 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
509 },
510 /* AP */
511 {
512 .limits = wlan_hdd_ap_iface_limit,
513 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530514 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
516 },
517 /* P2P */
518 {
519 .limits = wlan_hdd_p2p_iface_limit,
520 .num_different_channels = 2,
521 .max_interfaces = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
523 },
524 /* STA + AP */
525 {
526 .limits = wlan_hdd_sta_ap_iface_limit,
527 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
530 .beacon_int_infra_match = true,
531 },
532 /* STA + P2P */
533 {
534 .limits = wlan_hdd_sta_p2p_iface_limit,
535 .num_different_channels = 2,
536 /* one interface reserved for P2PDEV dedicated usage */
537 .max_interfaces = 4,
538 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
539 .beacon_int_infra_match = true,
540 },
541 /* STA + P2P GO + SAP */
542 {
543 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
544 /* we can allow 3 channels for three different persona
545 * but due to firmware limitation, allow max 2 concrnt channels.
546 */
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* SAP + P2P */
554 {
555 .limits = wlan_hdd_sap_p2p_iface_limit,
556 .num_different_channels = 2,
557 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
558 .max_interfaces = 3,
559 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
560 .beacon_int_infra_match = true,
561 },
562 /* P2P + P2P */
563 {
564 .limits = wlan_hdd_p2p_p2p_iface_limit,
565 .num_different_channels = 2,
566 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
567 .max_interfaces = 3,
568 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
569 .beacon_int_infra_match = true,
570 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530571 /* Monitor */
572 {
573 .limits = wlan_hdd_mon_iface_limit,
574 .max_interfaces = 3,
575 .num_different_channels = 2,
576 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
577 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579
580static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530581struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583#ifdef WLAN_NL80211_TESTMODE
584enum wlan_hdd_tm_attr {
585 WLAN_HDD_TM_ATTR_INVALID = 0,
586 WLAN_HDD_TM_ATTR_CMD = 1,
587 WLAN_HDD_TM_ATTR_DATA = 2,
588 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
589 WLAN_HDD_TM_ATTR_TYPE = 4,
590 /* keep last */
591 WLAN_HDD_TM_ATTR_AFTER_LAST,
592 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
593};
594
595enum wlan_hdd_tm_cmd {
596 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
597 WLAN_HDD_TM_CMD_WLAN_HB = 1,
598};
599
600#define WLAN_HDD_TM_DATA_MAX_LEN 5000
601
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530602enum wlan_hdd_vendor_ie_access_policy {
603 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
604 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
605};
606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
608 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
609 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
610 .len = WLAN_HDD_TM_DATA_MAX_LEN},
611};
612#endif /* WLAN_NL80211_TESTMODE */
613
614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
615static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
616 .flags = WIPHY_WOWLAN_MAGIC_PKT,
617 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
618 .pattern_min_len = 1,
619 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
620};
621#endif
622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530624 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
625 * @flags: Pointer to the flags to Add channel switch flag.
626 *
627 * This Function adds Channel Switch support flag, if channel switch is
628 * supported by kernel.
629 * Return: void.
630 */
631#ifdef CHANNEL_SWITCH_SUPPORTED
632static inline void hdd_add_channel_switch_support(uint32_t *flags)
633{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800634 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 return;
636}
637#else
638static inline void hdd_add_channel_switch_support(uint32_t *flags)
639{
640 return;
641}
642#endif
643
Manikandan Mohan22b83722015-12-15 15:03:23 -0800644#ifdef FEATURE_WLAN_TDLS
645
646/* TDLS capabilities params */
647#define PARAM_MAX_TDLS_SESSION \
648 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
649#define PARAM_TDLS_FEATURE_SUPPORT \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
651
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530652/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
654 * @wiphy: WIPHY structure pointer
655 * @wdev: Wireless device structure pointer
656 * @data: Pointer to the data received
657 * @data_len: Length of the data received
658 *
659 * This function provides TDLS capabilities
660 *
661 * Return: 0 on success and errno on failure
662 */
663static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
664 struct wireless_dev *wdev,
665 const void *data,
666 int data_len)
667{
668 int status;
669 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
670 struct sk_buff *skb;
671 uint32_t set = 0;
672
Jeff Johnson1f61b612016-02-12 16:28:33 -0800673 ENTER_DEV(wdev->netdev);
674
Anurag Chouhan6d760662016-02-20 16:05:43 +0530675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 hdd_err("Command not allowed in FTM mode");
677 return -EPERM;
678 }
679
680 status = wlan_hdd_validate_context(hdd_ctx);
681 if (status)
682 return status;
683
684 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
685 NLMSG_HDRLEN);
686 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700687 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 goto fail;
689 }
690
691 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
694 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 goto fail;
697 }
698 } else {
699 set = set | WIFI_TDLS_SUPPORT;
700 set = set | (hdd_ctx->config->fTDLSExternalControl ?
701 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
702 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
703 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
706 hdd_ctx->max_num_tdls_sta) ||
707 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
708 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 goto fail;
711 }
712 }
713 return cfg80211_vendor_cmd_reply(skb);
714fail:
715 if (skb)
716 kfree_skb(skb);
717 return -EINVAL;
718}
719
720/**
721 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
722 * @wiphy: WIPHY structure pointer
723 * @wdev: Wireless device structure pointer
724 * @data: Pointer to the data received
725 * @data_len: Length of the data received
726 *
727 * This function provides TDLS capabilities
728 *
729 * Return: 0 on success and errno on failure
730 */
731static int
732wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
733 struct wireless_dev *wdev,
734 const void *data,
735 int data_len)
736{
737 int ret;
738
739 cds_ssr_protect(__func__);
740 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
741 data, data_len);
742 cds_ssr_unprotect(__func__);
743
744 return ret;
745}
746#endif
747
748#ifdef QCA_HT_2040_COEX
749static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
750#endif
751
752#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
753/*
754 * FUNCTION: wlan_hdd_send_avoid_freq_event
755 * This is called when wlan driver needs to send vendor specific
756 * avoid frequency range event to userspace
757 */
758int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
759 tHddAvoidFreqList *pAvoidFreqList)
760{
761 struct sk_buff *vendor_event;
762
763 ENTER();
764
765 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 return -EINVAL;
768 }
769
770 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
776 NULL,
777 sizeof(tHddAvoidFreqList),
778 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
779 GFP_KERNEL);
780 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
786 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
787
788 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
789
790 EXIT();
791 return 0;
792}
793#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
794
795/* vendor specific events */
796static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
797#ifdef FEATURE_WLAN_CH_AVOID
798 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
799 .vendor_id =
800 QCA_NL80211_VENDOR_ID,
801 .subcmd =
802 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
803 },
804#endif /* FEATURE_WLAN_CH_AVOID */
805
806#ifdef WLAN_FEATURE_NAN
807 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_NAN
812 },
813#endif
814
815#ifdef WLAN_FEATURE_STATS_EXT
816 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
821 },
822#endif /* WLAN_FEATURE_STATS_EXT */
823#ifdef FEATURE_WLAN_EXTSCAN
824 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
829 },
830 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
831 .vendor_id =
832 QCA_NL80211_VENDOR_ID,
833 .subcmd =
834 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
835 },
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
837 .
838 vendor_id
839 =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .
850 subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd
860 =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .subcmd =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
872 .vendor_id =
873 QCA_NL80211_VENDOR_ID,
874 .subcmd =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
878 .
879 vendor_id
880 =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .
899 subcmd
900 =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd
919 =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
933 .vendor_id = QCA_NL80211_VENDOR_ID,
934 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
935 },
936 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
937 .vendor_id = QCA_NL80211_VENDOR_ID,
938 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
939 },
940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
979#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
980 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
981 .vendor_id =
982 QCA_NL80211_VENDOR_ID,
983 .subcmd =
984 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
985 },
986 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
987 .vendor_id = QCA_NL80211_VENDOR_ID,
988 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
989 },
990#ifdef WLAN_FEATURE_ROAM_OFFLOAD
991 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
992 .vendor_id =
993 QCA_NL80211_VENDOR_ID,
994 .subcmd =
995 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
996 },
997#endif
998 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
999 .vendor_id =
1000 QCA_NL80211_VENDOR_ID,
1001 .subcmd =
1002 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1003 },
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1027 },
1028#ifdef FEATURE_WLAN_EXTSCAN
1029 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1030 .vendor_id = QCA_NL80211_VENDOR_ID,
1031 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1032 },
1033 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1034 .vendor_id = QCA_NL80211_VENDOR_ID,
1035 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1036 },
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1044 },
1045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
1201
1202 /*
1203 * Check if AP+AP case, once primary AP chooses a DFS
1204 * channel secondary AP should always follow primary APs channel
1205 */
1206 if (!cds_concurrent_beaconing_sessions_running())
1207 return 0;
1208
1209 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1210 if (!con_sap_adapter)
1211 return 0;
1212
1213 sap_config = &adapter->sessionCtx.ap.sapConfig;
1214 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1215 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1216
1217 if (!CDS_IS_DFS_CH(con_ch))
1218 return 0;
1219
Jeff Johnson020db452016-06-29 14:37:26 -07001220 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001222 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel = con_ch;
1224
1225 if (con_sap_config->acs_cfg.acs_mode == true) {
1226 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1227 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Primary AP channel config error");
1229 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 con_ch, con_sap_config->acs_cfg.pri_ch,
1231 con_sap_config->acs_cfg.ht_sec_ch);
1232 return -EINVAL;
1233 }
1234 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1235 * MCC restriction. So free ch list allocated in do_acs
1236 * func for Sec AP and realloc for Pri AP ch list size
1237 */
1238 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301239 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 &con_sap_config->acs_cfg,
1243 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 sizeof(uint8_t) *
1246 con_sap_config->acs_cfg.ch_list_count);
1247 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001248 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 return -ENOMEM;
1250 }
1251
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 con_sap_config->acs_cfg.ch_list,
1254 con_sap_config->acs_cfg.ch_list_count);
1255
1256 } else {
1257 sap_config->acs_cfg.pri_ch = con_ch;
1258 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1259 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1260 }
1261
1262 return con_ch;
1263}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264
1265/**
1266 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1267 * @sap_cfg: pointer to SAP config struct
1268 *
1269 * This function sets the default ACS start and end channel for the given band
1270 * and also parses the given ACS channel list.
1271 *
1272 * Return: None
1273 */
1274
1275static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1276 bool vht_enabled)
1277{
1278 int i;
1279 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1280 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001281 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1282 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1284 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001285 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1286 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001293 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 }
1296
1297 if (ht_enabled)
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1299
1300 if (vht_enabled)
1301 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1302
1303
1304 /* Parse ACS Chan list from hostapd */
1305 if (!sap_cfg->acs_cfg.ch_list)
1306 return;
1307
1308 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1309 sap_cfg->acs_cfg.end_ch =
1310 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1311 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301312 /* avoid channel as start channel */
1313 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1314 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1316 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1317 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1318 }
1319}
1320
1321
1322static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1323
1324/**
1325 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1326 * @adapter: pointer to SAP adapter struct
1327 *
1328 * This function starts the ACS procedure if there are no
1329 * constraints like MBSSID DFS restrictions.
1330 *
1331 * Return: Status of ACS Start procedure
1332 */
1333
1334static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1335{
1336
1337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1338 tsap_Config_t *sap_config;
1339 tpWLAN_SAPEventCB acs_event_callback;
1340 int status;
1341
1342 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301343 if (hdd_ctx->acs_policy.acs_channel)
1344 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1345 else
1346 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347
1348 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1349 if (status < 0) {
1350 return status;
1351 } else {
1352 if (status > 0) {
1353 /*notify hostapd about channel override */
1354 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1355 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1356 return 0;
1357 }
1358 }
1359 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1360 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001361 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return -EINVAL;
1363 }
1364
1365 acs_event_callback = hdd_hostapd_sap_event_cb;
1366
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301367 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301368 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 acs_event_callback, sap_config, adapter->dev);
1373
1374
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379 sap_config->acs_cfg.acs_mode = true;
1380 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1381
1382 return 0;
1383}
1384
1385/**
1386 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1387 * @wiphy: Linux wiphy struct pointer
1388 * @wdev: Linux wireless device struct pointer
1389 * @data: ACS information from hostapd
1390 * @data_len: ACS information length
1391 *
1392 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1393 * and starts ACS procedure.
1394 *
1395 * Return: ACS procedure start status
1396 */
1397
1398static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1399 struct wireless_dev *wdev,
1400 const void *data, int data_len)
1401{
1402 struct net_device *ndev = wdev->netdev;
1403 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1405 tsap_Config_t *sap_config;
1406 struct sk_buff *temp_skbuff;
1407 int status = -EINVAL, i = 0;
1408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1409 bool ht_enabled, ht40_enabled, vht_enabled;
1410 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301411 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
1413 /* ***Note*** Donot set SME config related to ACS operation here because
1414 * ACS operation is not synchronouse and ACS for Second AP may come when
1415 * ACS operation for first AP is going on. So only do_acs is split to
1416 * seperate start_acs routine. Also SME-PMAC struct that is used to
1417 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1418 * config shall be set only from start_acs.
1419 */
1420
1421 /* nla_policy Policy template. Policy not applied as some attributes are
1422 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1423 *
1424 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1425 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1430 */
1431
Jeff Johnson1f61b612016-02-12 16:28:33 -08001432 ENTER_DEV(ndev);
1433
Anurag Chouhan6d760662016-02-20 16:05:43 +05301434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_err("Command not allowed in FTM mode");
1436 return -EPERM;
1437 }
1438
1439 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001440 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 return -EPERM;
1442 }
1443
1444 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301445 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301447
Naveen Rawat64e477e2016-05-20 10:34:56 -07001448 if (cds_is_sub_20_mhz_enabled()) {
1449 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1450 status = -EINVAL;
1451 goto out;
1452 }
1453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301455 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456
1457 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1458 NULL);
1459 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 goto out;
1462 }
1463
1464 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001465 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 goto out;
1467 }
1468 sap_config->acs_cfg.hw_mode = nla_get_u8(
1469 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1472 ht_enabled =
1473 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1474 else
1475 ht_enabled = 0;
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1478 ht40_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1480 else
1481 ht40_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1484 vht_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1486 else
1487 vht_enabled = 0;
1488
1489 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1490 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1491 } else {
1492 if (ht_enabled && ht40_enabled)
1493 ch_width = 40;
1494 else
1495 ch_width = 20;
1496 }
1497 if (ch_width == 80)
1498 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1499 else if (ch_width == 40)
1500 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1501 else
1502 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1503
1504 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1505 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1506 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1507 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1508 * since it contains the frequency values of the channels in
1509 * the channel list.
1510 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1511 * is present
1512 */
1513 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1514 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1515 sap_config->acs_cfg.ch_list_count = nla_len(
1516 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
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 sizeof(uint8_t) *
1520 sap_config->acs_cfg.ch_list_count);
1521 if (sap_config->acs_cfg.ch_list == NULL)
1522 goto out;
1523
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301524 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001525 sap_config->acs_cfg.ch_list_count);
1526 }
1527 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1528 uint32_t *freq =
1529 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1530 sap_config->acs_cfg.ch_list_count = nla_len(
1531 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1532 sizeof(uint32_t);
1533 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301534 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 sap_config->acs_cfg.ch_list_count);
1536 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001537 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 status = -ENOMEM;
1539 goto out;
1540 }
1541
1542 /* convert frequency to channel */
1543 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1544 sap_config->acs_cfg.ch_list[i] =
1545 ieee80211_frequency_to_channel(freq[i]);
1546 }
1547 }
1548
1549 hdd_debug("get pcl for DO_ACS vendor command");
1550
1551 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001552 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301553 sap_config->acs_cfg.pcl_channels,
1554 &sap_config->acs_cfg.pcl_ch_count,
1555 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301556 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001557 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 /* ACS override for android */
1560 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
Jeff Johnson020db452016-06-29 14:37:26 -07001561 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001562 vht_enabled = 1;
1563 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1564 sap_config->acs_cfg.ch_width =
1565 hdd_ctx->config->vhtChannelWidth;
1566 /* No VHT80 in 2.4G so perform ACS accordingly */
1567 if (sap_config->acs_cfg.end_ch <= 14 &&
1568 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1569 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1570 }
1571
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301572 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1573
Jeff Johnson020db452016-06-29 14:37:26 -07001574 hdd_notice("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001575 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1576 ch_width, ht_enabled, vht_enabled,
1577 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1578
1579 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001580 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 sap_config->acs_cfg.ch_list_count);
1582 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001583 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 }
1585 sap_config->acs_cfg.acs_mode = true;
1586 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001587 /* ***Note*** Completion variable usage is not allowed
1588 * here since ACS scan operation may take max 2.2 sec
1589 * for 5G band:
1590 * 9 Active channel X 40 ms active scan time +
1591 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1593 * for this long. So we split up the scanning part.
1594 */
1595 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001596 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597 status = 0;
1598 } else {
1599 status = wlan_hdd_cfg80211_start_acs(adapter);
1600 }
1601
1602out:
1603 if (0 == status) {
1604 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1605 NLMSG_HDRLEN);
1606 if (temp_skbuff != NULL)
1607 return cfg80211_vendor_cmd_reply(temp_skbuff);
1608 }
1609
1610 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1611
1612 return status;
1613}
1614
1615 /**
1616 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1617 * @wiphy: Linux wiphy struct pointer
1618 * @wdev: Linux wireless device struct pointer
1619 * @data: ACS information from hostapd
1620 * @data_len: ACS information len
1621 *
1622 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1623 * and starts ACS procedure.
1624 *
1625 * Return: ACS procedure start status
1626 */
1627
1628static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1629 struct wireless_dev *wdev,
1630 const void *data, int data_len)
1631{
1632 int ret;
1633
1634 cds_ssr_protect(__func__);
1635 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1636 cds_ssr_unprotect(__func__);
1637
1638 return ret;
1639}
1640
1641/**
1642 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1643 * @work: Linux workqueue struct pointer for ACS work
1644 *
1645 * This function starts the ACS procedure which was marked pending when an ACS
1646 * procedure was in progress for a concurrent SAP interface.
1647 *
1648 * Return: None
1649 */
1650
1651static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1652{
1653 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1654 acs_pending_work.work);
1655 wlan_hdd_cfg80211_start_acs(adapter);
1656}
1657
1658/**
1659 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1660 * @adapter: Pointer to SAP adapter struct
1661 * @pri_channel: SAP ACS procedure selected Primary channel
1662 * @sec_channel: SAP ACS procedure selected secondary channel
1663 *
1664 * This is a callback function from SAP module on ACS procedure is completed.
1665 * This function send the ACS selected channel information to hostapd
1666 *
1667 * Return: None
1668 */
1669
1670void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1671{
1672 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1673 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1674 struct sk_buff *vendor_event;
1675 int ret_val;
1676 hdd_adapter_t *con_sap_adapter;
1677 uint16_t ch_width;
1678
1679 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001680 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1682 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1683 GFP_KERNEL);
1684
1685 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001686 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001687 return;
1688 }
1689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 ret_val = nla_put_u8(vendor_event,
1691 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1692 sap_cfg->acs_cfg.pri_ch);
1693 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001694 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001695 kfree_skb(vendor_event);
1696 return;
1697 }
1698
1699 ret_val = nla_put_u8(vendor_event,
1700 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1701 sap_cfg->acs_cfg.ht_sec_ch);
1702 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001703 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704 kfree_skb(vendor_event);
1705 return;
1706 }
1707
1708 ret_val = nla_put_u8(vendor_event,
1709 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1710 sap_cfg->acs_cfg.vht_seg0_center_ch);
1711 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001712 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001713 kfree_skb(vendor_event);
1714 return;
1715 }
1716
1717 ret_val = nla_put_u8(vendor_event,
1718 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1719 sap_cfg->acs_cfg.vht_seg1_center_ch);
1720 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001721 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 kfree_skb(vendor_event);
1723 return;
1724 }
1725
1726 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1727 ch_width = 80;
1728 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1729 ch_width = 40;
1730 else
1731 ch_width = 20;
1732
1733 ret_val = nla_put_u16(vendor_event,
1734 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1735 ch_width);
1736 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001737 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 kfree_skb(vendor_event);
1739 return;
1740 }
1741 if (sap_cfg->acs_cfg.pri_ch > 14)
1742 ret_val = nla_put_u8(vendor_event,
1743 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1744 QCA_ACS_MODE_IEEE80211A);
1745 else
1746 ret_val = nla_put_u8(vendor_event,
1747 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1748 QCA_ACS_MODE_IEEE80211G);
1749
1750 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001751 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752 kfree_skb(vendor_event);
1753 return;
1754 }
1755
Jeff Johnson46b40792016-06-29 14:03:14 -07001756 hdd_notice("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001757 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1758 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1759 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1760
1761 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1762 /* ***Note*** As already mentioned Completion variable usage is not
1763 * allowed here since ACS scan operation may take max 2.2 sec.
1764 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1765 * operation.
1766 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1767 * when Primary AP ACS is complete and secondary AP ACS is started here
1768 * immediately, Primary AP start_bss may come inbetween ACS operation
1769 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1770 * delay. This path and below constraint will be removed on sessionizing
1771 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1772 * As per design constraint user space control application must take
1773 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1774 * this code path. Sec AP hostapd should be started after Primary AP
1775 * start beaconing which can be confirmed by getchannel iwpriv command
1776 */
1777
1778 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1779 if (con_sap_adapter &&
1780 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1782 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001783 /* Lets give 500ms for OBSS + START_BSS to complete */
1784 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1785 msecs_to_jiffies(500));
1786 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1787 }
1788
1789 return;
1790}
1791
1792static int
1793__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1794 struct wireless_dev *wdev,
1795 const void *data,
1796 int data_len)
1797{
1798 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1799 struct sk_buff *skb = NULL;
1800 uint32_t fset = 0;
1801 int ret;
1802
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001803 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301804
Anurag Chouhan6d760662016-02-20 16:05:43 +05301805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 hdd_err("Command not allowed in FTM mode");
1807 return -EPERM;
1808 }
1809
1810 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301811 if (ret)
1812 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813
1814 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001815 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 fset |= WIFI_FEATURE_INFRA;
1817 }
1818 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001819 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 fset |= WIFI_FEATURE_INFRA_5G;
1821 }
1822#ifdef WLAN_FEATURE_P2P
1823 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1824 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001825 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 fset |= WIFI_FEATURE_P2P;
1827 }
1828#endif
1829 fset |= WIFI_FEATURE_SOFT_AP;
1830
1831 /* HOTSPOT is a supplicant feature, enable it by default */
1832 fset |= WIFI_FEATURE_HOTSPOT;
1833
1834#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301835 if (pHddCtx->config->extscan_enabled &&
1836 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001837 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1839 }
1840#endif
1841 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001842 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 fset |= WIFI_FEATURE_NAN;
1844 }
1845 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001846 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 fset |= WIFI_FEATURE_D2D_RTT;
1848 fset |= WIFI_FEATURE_D2AP_RTT;
1849 }
1850#ifdef FEATURE_WLAN_SCAN_PNO
1851 if (pHddCtx->config->configPNOScanSupport &&
1852 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001853 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854 fset |= WIFI_FEATURE_PNO;
1855 }
1856#endif
1857 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1858#ifdef FEATURE_WLAN_TDLS
1859 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1860 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001861 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 fset |= WIFI_FEATURE_TDLS;
1863 }
1864 if (sme_is_feature_supported_by_fw(TDLS) &&
1865 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1866 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001867 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1869 }
1870#endif
1871#ifdef WLAN_AP_STA_CONCURRENCY
1872 fset |= WIFI_FEATURE_AP_STA;
1873#endif
1874 fset |= WIFI_FEATURE_RSSI_MONITOR;
1875
1876 if (hdd_link_layer_stats_supported())
1877 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1878
1879 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1880 NLMSG_HDRLEN);
1881 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001882 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 return -EINVAL;
1884 }
Jeff Johnson020db452016-06-29 14:37:26 -07001885 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001887 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 goto nla_put_failure;
1889 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301890 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301891 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892nla_put_failure:
1893 kfree_skb(skb);
1894 return -EINVAL;
1895}
1896
1897/**
1898 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1899 * @wiphy: pointer to wireless wiphy structure.
1900 * @wdev: pointer to wireless_dev structure.
1901 * @data: Pointer to the data to be passed via vendor interface
1902 * @data_len:Length of the data to be passed
1903 *
1904 * Return: Return the Success or Failure code.
1905 */
1906static int
1907wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1908 struct wireless_dev *wdev,
1909 const void *data, int data_len)
1910{
1911 int ret = 0;
1912
1913 cds_ssr_protect(__func__);
1914 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1915 data, data_len);
1916 cds_ssr_unprotect(__func__);
1917
1918 return ret;
1919}
1920
1921/**
1922 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1923 * @wiphy: pointer to wireless wiphy structure.
1924 * @wdev: pointer to wireless_dev structure.
1925 * @data: Pointer to the data to be passed via vendor interface
1926 * @data_len:Length of the data to be passed
1927 *
1928 * Set the MAC address that is to be used for scanning.
1929 *
1930 * Return: Return the Success or Failure code.
1931 */
1932static int
1933__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1934 struct wireless_dev *wdev,
1935 const void *data,
1936 int data_len)
1937{
1938 tpSirScanMacOui pReqMsg = NULL;
1939 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1940 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301941 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 int ret;
1943
Jeff Johnson1f61b612016-02-12 16:28:33 -08001944 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945
Anurag Chouhan6d760662016-02-20 16:05:43 +05301946 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 hdd_err("Command not allowed in FTM mode");
1948 return -EPERM;
1949 }
1950
1951 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301952 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
1955 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001956 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 return -ENOTSUPP;
1958 }
1959
1960 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1961 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001962 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 return -EINVAL;
1964 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301965 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001967 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return -ENOMEM;
1969 }
1970 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001971 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 goto fail;
1973 }
1974 nla_memcpy(&pReqMsg->oui[0],
1975 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1976 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001977 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 pReqMsg->oui[1], pReqMsg->oui[2]);
1979 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301980 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001981 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 goto fail;
1983 }
1984 return 0;
1985fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301986 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 return -EINVAL;
1988}
1989
1990/**
1991 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1992 * @wiphy: pointer to wireless wiphy structure.
1993 * @wdev: pointer to wireless_dev structure.
1994 * @data: Pointer to the data to be passed via vendor interface
1995 * @data_len:Length of the data to be passed
1996 *
1997 * Set the MAC address that is to be used for scanning. This is an
1998 * SSR-protecting wrapper function.
1999 *
2000 * Return: Return the Success or Failure code.
2001 */
2002static int
2003wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2004 struct wireless_dev *wdev,
2005 const void *data,
2006 int data_len)
2007{
2008 int ret;
2009
2010 cds_ssr_protect(__func__);
2011 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2012 data, data_len);
2013 cds_ssr_unprotect(__func__);
2014
2015 return ret;
2016}
2017
2018/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302019 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2020 * @wiphy: pointer phy adapter
2021 * @wdev: pointer to wireless device structure
2022 * @data: pointer to data buffer
2023 * @data_len: length of data
2024 *
2025 * This routine will give concurrency matrix
2026 *
2027 * Return: int status code
2028 */
2029static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2030 struct wireless_dev *wdev,
2031 const void *data,
2032 int data_len)
2033{
2034 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2035 uint8_t i, feature_sets, max_feature_sets;
2036 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2037 struct sk_buff *reply_skb;
2038 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2039 int ret;
2040
2041 ENTER_DEV(wdev->netdev);
2042
2043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2044 hdd_err("Command not allowed in FTM mode");
2045 return -EPERM;
2046 }
2047
2048 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302049 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302050 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302051
2052 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2053 data, data_len, NULL)) {
2054 hdd_err("Invalid ATTR");
2055 return -EINVAL;
2056 }
2057
2058 /* Parse and fetch max feature set */
2059 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2060 hdd_err("Attr max feature set size failed");
2061 return -EINVAL;
2062 }
2063 max_feature_sets = nla_get_u32(tb[
2064 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2065 hdd_info("Max feature set size: %d", max_feature_sets);
2066
2067 /* Fill feature combination matrix */
2068 feature_sets = 0;
2069 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002070 WIFI_FEATURE_P2P;
2071 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2072 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302073 /* Add more feature combinations here */
2074
2075 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002076 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302077 hdd_info("Feature set matrix");
2078 for (i = 0; i < feature_sets; i++)
2079 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2080
2081 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2082 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2083 if (!reply_skb) {
2084 hdd_err("Feature set matrix: buffer alloc fail");
2085 return -ENOMEM;
2086 }
2087
2088 if (nla_put_u32(reply_skb,
2089 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2090 feature_sets) ||
2091 nla_put(reply_skb,
2092 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2093 sizeof(u32) * feature_sets,
2094 feature_set_matrix)) {
2095 hdd_err("nla put fail");
2096 kfree_skb(reply_skb);
2097 return -EINVAL;
2098 }
2099 return cfg80211_vendor_cmd_reply(reply_skb);
2100}
2101
2102/**
2103 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2104 * @wiphy: pointer to wireless wiphy structure.
2105 * @wdev: pointer to wireless_dev structure.
2106 * @data: Pointer to the data to be passed via vendor interface
2107 * @data_len:Length of the data to be passed
2108 *
2109 * Retrieves the concurrency feature set matrix
2110 *
2111 * Return: 0 on success, negative errno on failure
2112 */
2113static int
2114wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2115 struct wireless_dev *wdev,
2116 const void *data,
2117 int data_len)
2118{
2119 int ret;
2120
2121 cds_ssr_protect(__func__);
2122 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2123 data, data_len);
2124 cds_ssr_unprotect(__func__);
2125
2126 return ret;
2127}
2128
2129/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2131 * @feature_flags: pointer to the byte array of features.
2132 * @feature: Feature to be turned ON in the byte array.
2133 *
2134 * Return: None
2135 *
2136 * This is called to turn ON or SET the feature flag for the requested feature.
2137 **/
2138#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002139static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2140 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141{
2142 uint32_t index;
2143 uint8_t bit_mask;
2144
2145 index = feature / NUM_BITS_IN_BYTE;
2146 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2147 feature_flags[index] |= bit_mask;
2148}
2149
2150/**
2151 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2152 * @wiphy: pointer to wireless wiphy structure.
2153 * @wdev: pointer to wireless_dev structure.
2154 * @data: Pointer to the data to be passed via vendor interface
2155 * @data_len:Length of the data to be passed
2156 *
2157 * This is called when wlan driver needs to send supported feature set to
2158 * supplicant upon a request/query from the supplicant.
2159 *
2160 * Return: Return the Success or Failure code.
2161 **/
2162#define MAX_CONCURRENT_CHAN_ON_24G 2
2163#define MAX_CONCURRENT_CHAN_ON_5G 2
2164static int
2165__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2166 struct wireless_dev *wdev,
2167 const void *data, int data_len)
2168{
2169 struct sk_buff *skb = NULL;
2170 uint32_t dbs_capability = 0;
2171 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302172 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 int ret_val;
2174
2175 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2176 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2177
Jeff Johnson1f61b612016-02-12 16:28:33 -08002178 ENTER_DEV(wdev->netdev);
2179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2181 if (ret_val)
2182 return ret_val;
2183
Anurag Chouhan6d760662016-02-20 16:05:43 +05302184 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 hdd_err("Command not allowed in FTM mode");
2186 return -EPERM;
2187 }
2188
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002189 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002190 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 wlan_hdd_cfg80211_set_feature(feature_flags,
2192 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2193 }
2194
2195 wlan_hdd_cfg80211_set_feature(feature_flags,
2196 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2197 if (wma_is_scan_simultaneous_capable())
2198 wlan_hdd_cfg80211_set_feature(feature_flags,
2199 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002200
2201 if (wma_is_p2p_lo_capable())
2202 wlan_hdd_cfg80211_set_feature(feature_flags,
2203 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2206 NLMSG_HDRLEN);
2207
2208 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002209 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210 return -ENOMEM;
2211 }
2212
2213 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2214 sizeof(feature_flags), feature_flags))
2215 goto nla_put_failure;
2216
2217 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302218 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 if (one_by_one_dbs)
2220 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2221
2222 if (two_by_two_dbs)
2223 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2224
2225 if (!one_by_one_dbs && !two_by_two_dbs)
2226 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2227 } else {
2228 hdd_err("wma_get_dbs_hw_mode failed");
2229 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2230 }
2231
2232 hdd_info("dbs_capability is %d", dbs_capability);
2233
2234 if (nla_put_u32(skb,
2235 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2236 MAX_CONCURRENT_CHAN_ON_24G))
2237 goto nla_put_failure;
2238
2239 if (nla_put_u32(skb,
2240 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2241 MAX_CONCURRENT_CHAN_ON_5G))
2242 goto nla_put_failure;
2243
2244 return cfg80211_vendor_cmd_reply(skb);
2245
2246nla_put_failure:
2247 kfree_skb(skb);
2248 return -EINVAL;
2249}
2250
2251/**
2252 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2253 * @wiphy: pointer to wireless wiphy structure.
2254 * @wdev: pointer to wireless_dev structure.
2255 * @data: Pointer to the data to be passed via vendor interface
2256 * @data_len:Length of the data to be passed
2257 *
2258 * This is called when wlan driver needs to send supported feature set to
2259 * supplicant upon a request/query from the supplicant.
2260 *
2261 * Return: Return the Success or Failure code.
2262 */
2263static int
2264wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2265 struct wireless_dev *wdev,
2266 const void *data, int data_len)
2267{
2268 int ret;
2269
2270 cds_ssr_protect(__func__);
2271 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2272 data, data_len);
2273 cds_ssr_unprotect(__func__);
2274
2275 return ret;
2276}
2277
2278
2279/**
2280 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2281 * @wiphy: The wiphy structure
2282 * @wdev: The wireless device
2283 * @data: Data passed by framework
2284 * @data_len: Parameters to be configured passed as data
2285 *
2286 * The roaming related parameters are configured by the framework
2287 * using this interface.
2288 *
2289 * Return: Return either success or failure code.
2290 */
2291static int
2292__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2293 struct wireless_dev *wdev, const void *data, int data_len)
2294{
2295 struct net_device *dev = wdev->netdev;
2296 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2297 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2298 uint8_t session_id;
2299 struct roam_ext_params roam_params;
2300 uint32_t cmd_type, req_id;
2301 struct nlattr *curr_attr;
2302 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2303 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2304 int rem, i;
2305 uint32_t buf_len = 0;
2306 int ret;
2307
Jeff Johnson1f61b612016-02-12 16:28:33 -08002308 ENTER_DEV(dev);
2309
Anurag Chouhan6d760662016-02-20 16:05:43 +05302310 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 hdd_err("Command not allowed in FTM mode");
2312 return -EPERM;
2313 }
2314
2315 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302316 if (ret)
2317 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318
2319 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2320 data, data_len,
2321 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002322 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 return -EINVAL;
2324 }
2325 /* Parse and fetch Command Type*/
2326 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002327 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 goto fail;
2329 }
2330 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302331 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2333 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002334 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 goto fail;
2336 }
2337 req_id = nla_get_u32(
2338 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002339 hdd_debug("Req Id (%d)", req_id);
2340 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341 switch (cmd_type) {
2342 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2343 i = 0;
2344 nla_for_each_nested(curr_attr,
2345 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2346 rem) {
2347 if (nla_parse(tb2,
2348 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2349 nla_data(curr_attr), nla_len(curr_attr),
2350 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002351 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002352 goto fail;
2353 }
2354 /* Parse and Fetch allowed SSID list*/
2355 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002356 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 goto fail;
2358 }
2359 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2360 /*
2361 * Upper Layers include a null termination character.
2362 * Check for the actual permissible length of SSID and
2363 * also ensure not to copy the NULL termination
2364 * character to the driver buffer.
2365 */
2366 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2367 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2368 nla_memcpy(
2369 roam_params.ssid_allowed_list[i].ssId,
2370 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2371 buf_len - 1);
2372 roam_params.ssid_allowed_list[i].length =
2373 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002374 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 roam_params.ssid_allowed_list[i].length,
2376 roam_params.ssid_allowed_list[i].ssId,
2377 roam_params.ssid_allowed_list[i].length);
2378 i++;
2379 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 }
2382 }
2383 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002384 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 roam_params.num_ssid_allowed_list);
2386 sme_update_roam_params(pHddCtx->hHal, session_id,
2387 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2388 break;
2389 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2390 /* Parse and fetch 5G Boost Threshold */
2391 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002392 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 goto fail;
2394 }
2395 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2396 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002397 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398 roam_params.raise_rssi_thresh_5g);
2399 /* Parse and fetch 5G Penalty Threshold */
2400 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002401 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002402 goto fail;
2403 }
2404 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2405 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002406 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002407 roam_params.drop_rssi_thresh_5g);
2408 /* Parse and fetch 5G Boost Factor */
2409 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002410 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 goto fail;
2412 }
2413 roam_params.raise_factor_5g = nla_get_u32(
2414 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002415 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416 roam_params.raise_factor_5g);
2417 /* Parse and fetch 5G Penalty factor */
2418 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002419 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 goto fail;
2421 }
2422 roam_params.drop_factor_5g = nla_get_u32(
2423 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002424 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 roam_params.drop_factor_5g);
2426 /* Parse and fetch 5G Max Boost */
2427 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002428 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 goto fail;
2430 }
2431 roam_params.max_raise_rssi_5g = nla_get_u32(
2432 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002433 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 roam_params.max_raise_rssi_5g);
2435 /* Parse and fetch Rssi Diff */
2436 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002437 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 goto fail;
2439 }
2440 roam_params.rssi_diff = nla_get_s32(
2441 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002442 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 roam_params.rssi_diff);
2444 /* Parse and fetch Alert Rssi Threshold */
2445 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002446 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 goto fail;
2448 }
2449 roam_params.alert_rssi_threshold = nla_get_u32(
2450 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002451 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 roam_params.alert_rssi_threshold);
2453 sme_update_roam_params(pHddCtx->hHal, session_id,
2454 roam_params,
2455 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2456 break;
2457 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2458 /* Parse and fetch Activate Good Rssi Roam */
2459 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 goto fail;
2462 }
2463 roam_params.good_rssi_roam = nla_get_s32(
2464 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002465 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 roam_params.good_rssi_roam);
2467 sme_update_roam_params(pHddCtx->hHal, session_id,
2468 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2469 break;
2470 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2471 /* Parse and fetch number of preferred BSSID */
2472 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002473 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 goto fail;
2475 }
2476 roam_params.num_bssid_favored = nla_get_u32(
2477 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 roam_params.num_bssid_favored);
2480 i = 0;
2481 nla_for_each_nested(curr_attr,
2482 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2483 rem) {
2484 if (nla_parse(tb2,
2485 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2486 nla_data(curr_attr), nla_len(curr_attr),
2487 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002488 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 goto fail;
2490 }
2491 /* Parse and fetch MAC address */
2492 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002493 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 goto fail;
2495 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002496 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302498 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002499 hdd_debug(MAC_ADDRESS_STR,
2500 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501 /* Parse and fetch preference factor*/
2502 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 goto fail;
2505 }
2506 roam_params.bssid_favored_factor[i] = nla_get_u32(
2507 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 roam_params.bssid_favored_factor[i]);
2510 i++;
2511 }
2512 sme_update_roam_params(pHddCtx->hHal, session_id,
2513 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2514 break;
2515 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2516 /* Parse and fetch number of blacklist BSSID */
2517 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002518 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 goto fail;
2520 }
2521 roam_params.num_bssid_avoid_list = nla_get_u32(
2522 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002523 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 roam_params.num_bssid_avoid_list);
2525 i = 0;
2526 nla_for_each_nested(curr_attr,
2527 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2528 rem) {
2529 if (nla_parse(tb2,
2530 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2531 nla_data(curr_attr), nla_len(curr_attr),
2532 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002533 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 goto fail;
2535 }
2536 /* Parse and fetch MAC address */
2537 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 goto fail;
2540 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002541 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302543 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002544 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002546 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 i++;
2548 }
2549 sme_update_roam_params(pHddCtx->hHal, session_id,
2550 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2551 break;
2552 }
2553 return 0;
2554fail:
2555 return -EINVAL;
2556}
2557
2558/**
2559 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2560 * @wiphy: pointer to wireless wiphy structure.
2561 * @wdev: pointer to wireless_dev structure.
2562 * @data: Pointer to the data to be passed via vendor interface
2563 * @data_len:Length of the data to be passed
2564 *
2565 * Return: Return the Success or Failure code.
2566 */
2567static int
2568wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2569 struct wireless_dev *wdev,
2570 const void *data,
2571 int data_len)
2572{
2573 int ret;
2574
2575 cds_ssr_protect(__func__);
2576 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2577 data, data_len);
2578 cds_ssr_unprotect(__func__);
2579
2580 return ret;
2581}
2582
2583static const struct nla_policy
2584wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2585 +1] = {
2586 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2587};
2588
2589/**
2590 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2591 * @hdd_ctx: HDD context
2592 * @device_mode: device mode
2593 * Return: bool
2594 */
2595static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002596 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597{
2598 hdd_adapter_t *adapter;
2599 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2600 hdd_ap_ctx_t *ap_ctx;
2601 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302602 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302604 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 &adapter_node);
2606
2607 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302608 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 adapter = adapter_node->pAdapter;
2610
2611 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002612 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 ap_ctx =
2614 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2615
2616 /*
2617 * if there is SAP already running on DFS channel,
2618 * do not disable scan on dfs channels. Note that
2619 * with SAP on DFS, there cannot be conurrency on
2620 * single radio. But then we can have multiple
2621 * radios !!
2622 */
2623 if (CHANNEL_STATE_DFS ==
2624 cds_get_channel_state(
2625 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002626 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002627 return true;
2628 }
2629 }
2630
2631 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002632 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633 sta_ctx =
2634 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2635
2636 /*
2637 * if STA is already connected on DFS channel,
2638 * do not disable scan on dfs channels
2639 */
2640 if (hdd_conn_is_connected(sta_ctx) &&
2641 (CHANNEL_STATE_DFS ==
2642 cds_get_channel_state(
2643 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002644 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 return true;
2646 }
2647 }
2648
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302649 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650 adapter_node,
2651 &next);
2652 adapter_node = next;
2653 }
2654
2655 return false;
2656}
2657
2658/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002659 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2660 * @hdd_ctx: HDD context within host driver
2661 * @adapter: Adapter pointer
2662 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2663 *
2664 * Loops through devices to see who is operating on DFS channels
2665 * and then disables/enables DFS channels by calling SME API.
2666 * Fails the disable request if any device is active on a DFS channel.
2667 *
2668 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002670
2671int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2672 hdd_adapter_t *adapter,
2673 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302676 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678
2679 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2680 if (no_dfs_flag) {
2681 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002682 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683
2684 if (true == status)
2685 return -EOPNOTSUPP;
2686
2687 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002688 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689
2690 if (true == status)
2691 return -EOPNOTSUPP;
2692 }
2693
2694 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2695
2696 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2697
2698 /*
2699 * call the SME API to tunnel down the new channel list
2700 * to the firmware
2701 */
2702 status = sme_handle_dfs_chan_scan(
2703 h_hal, hdd_ctx->config->enableDFSChnlScan);
2704
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302705 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 ret_val = 0;
2707
2708 /*
2709 * Clear the SME scan cache also. Note that the
2710 * clearing of scan results is independent of session;
2711 * so no need to iterate over
2712 * all sessions
2713 */
2714 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302715 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 ret_val = -EPERM;
2717 }
2718
2719 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002720 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 ret_val = 0;
2722 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002723 return ret_val;
2724}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002726/**
2727 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2728 * @wiphy: corestack handler
2729 * @wdev: wireless device
2730 * @data: data
2731 * @data_len: data length
2732 * Return: success(0) or reason code for failure
2733 */
2734static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2735 struct wireless_dev *wdev,
2736 const void *data,
2737 int data_len)
2738{
2739 struct net_device *dev = wdev->netdev;
2740 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2741 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2742 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2743 int ret_val;
2744 uint32_t no_dfs_flag = 0;
2745
Jeff Johnson1f61b612016-02-12 16:28:33 -08002746 ENTER_DEV(dev);
2747
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002748 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302749 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002750 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002751
2752 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2753 data, data_len,
2754 wlan_hdd_set_no_dfs_flag_config_policy)) {
2755 hdd_err("invalid attr");
2756 return -EINVAL;
2757 }
2758
2759 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2760 hdd_err("attr dfs flag failed");
2761 return -EINVAL;
2762 }
2763
2764 no_dfs_flag = nla_get_u32(
2765 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2766
Jeff Johnson020db452016-06-29 14:37:26 -07002767 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002768
2769 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002770 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002771 return -EINVAL;
2772 }
2773
2774 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2775 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 return ret_val;
2777}
2778
2779/**
2780 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2781 *
2782 * @wiphy: wiphy device pointer
2783 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002784 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785 * @data_len: Buffer length
2786 *
2787 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2788 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2789 *
2790 * Return: EOK or other error codes.
2791 */
2792
2793static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2794 struct wireless_dev *wdev,
2795 const void *data,
2796 int data_len)
2797{
2798 int ret;
2799
2800 cds_ssr_protect(__func__);
2801 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2802 data, data_len);
2803 cds_ssr_unprotect(__func__);
2804
2805 return ret;
2806}
2807
Manikandan Mohan80dea792016-04-28 16:36:48 -07002808static const struct nla_policy
2809wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2810 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2811};
2812
2813/**
2814 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2815 * @wiphy: wiphy device pointer
2816 * @wdev: wireless device pointer
2817 * @data: Vendor command data buffer
2818 * @data_len: Buffer length
2819 *
2820 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2821 * setup WISA Mode features.
2822 *
2823 * Return: Success(0) or reason code for failure
2824 */
2825static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2826 struct wireless_dev *wdev, const void *data, int data_len)
2827{
2828 struct net_device *dev = wdev->netdev;
2829 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2831 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2832 struct sir_wisa_params wisa;
2833 int ret_val;
2834 QDF_STATUS status;
2835 bool wisa_mode;
2836
2837 ENTER_DEV(dev);
2838 ret_val = wlan_hdd_validate_context(hdd_ctx);
2839 if (ret_val)
2840 goto err;
2841
2842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2843 hdd_err("Command not allowed in FTM mode");
2844 return -EPERM;
2845 }
2846
2847 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2848 wlan_hdd_wisa_cmd_policy)) {
2849 hdd_err("Invalid WISA cmd attributes");
2850 ret_val = -EINVAL;
2851 goto err;
2852 }
2853 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2854 hdd_err("Invalid WISA mode");
2855 ret_val = -EINVAL;
2856 goto err;
2857 }
2858
2859 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2860 hdd_info("WISA Mode: %d", wisa_mode);
2861 wisa.mode = wisa_mode;
2862 wisa.vdev_id = adapter->sessionId;
2863 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002864 if (!QDF_IS_STATUS_SUCCESS(status)) {
2865 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002866 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002867 }
2868 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2869 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2870 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002871err:
2872 EXIT();
2873 return ret_val;
2874}
2875
2876/**
2877 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2878 * @wiphy: corestack handler
2879 * @wdev: wireless device
2880 * @data: data
2881 * @data_len: data length
2882 *
2883 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2884 * setup WISA mode features.
2885 *
2886 * Return: Success(0) or reason code for failure
2887 */
2888static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2889 struct wireless_dev *wdev,
2890 const void *data,
2891 int data_len)
2892{
2893 int ret;
2894
2895 cds_ssr_protect(__func__);
2896 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2897 cds_ssr_unprotect(__func__);
2898
2899 return ret;
2900}
2901
Anurag Chouhan96919482016-07-13 16:36:57 +05302902/*
2903 * define short names for the global vendor params
2904 * used by __wlan_hdd_cfg80211_get_station_cmd()
2905 */
2906#define STATION_INVALID \
2907 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2908#define STATION_INFO \
2909 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2910#define STATION_ASSOC_FAIL_REASON \
2911 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2912#define STATION_MAX \
2913 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2914
2915static const struct nla_policy
2916hdd_get_station_policy[STATION_MAX + 1] = {
2917 [STATION_INFO] = {.type = NLA_FLAG},
2918 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2919};
2920
2921/**
2922 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2923 * @hdd_ctx: HDD context within host driver
2924 * @wdev: wireless device
2925 *
2926 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2927 * Validate cmd attributes and send the station info to upper layers.
2928 *
2929 * Return: Success(0) or reason code for failure
2930 */
2931static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2932 hdd_adapter_t *adapter)
2933{
2934 struct sk_buff *skb = NULL;
2935 uint32_t nl_buf_len;
2936 hdd_station_ctx_t *hdd_sta_ctx;
2937
2938 nl_buf_len = NLMSG_HDRLEN;
2939 nl_buf_len += sizeof(uint32_t);
2940 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2941
2942 if (!skb) {
2943 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2944 return -ENOMEM;
2945 }
2946
2947 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2948
2949 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2950 hdd_sta_ctx->conn_info.assoc_status_code)) {
2951 hdd_err("put fail");
2952 goto fail;
2953 }
2954 return cfg80211_vendor_cmd_reply(skb);
2955fail:
2956 if (skb)
2957 kfree_skb(skb);
2958 return -EINVAL;
2959}
2960
2961/**
2962 * hdd_map_auth_type() - transform auth type specific to
2963 * vendor command
2964 * @auth_type: csr auth type
2965 *
2966 * Return: Success(0) or reason code for failure
2967 */
2968static int hdd_convert_auth_type(uint32_t auth_type)
2969{
2970 uint32_t ret_val;
2971
2972 switch (auth_type) {
2973 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2974 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2975 break;
2976 case eCSR_AUTH_TYPE_SHARED_KEY:
2977 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2978 break;
2979 case eCSR_AUTH_TYPE_WPA:
2980 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2981 break;
2982 case eCSR_AUTH_TYPE_WPA_PSK:
2983 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2984 break;
2985 case eCSR_AUTH_TYPE_AUTOSWITCH:
2986 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
2987 break;
2988 case eCSR_AUTH_TYPE_WPA_NONE:
2989 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
2990 break;
2991 case eCSR_AUTH_TYPE_RSN:
2992 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
2993 break;
2994 case eCSR_AUTH_TYPE_RSN_PSK:
2995 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
2996 break;
2997 case eCSR_AUTH_TYPE_FT_RSN:
2998 ret_val = QCA_WLAN_AUTH_TYPE_FT;
2999 break;
3000 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3001 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3002 break;
3003 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3004 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3005 break;
3006 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3007 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3008 break;
3009 case eCSR_AUTH_TYPE_CCKM_WPA:
3010 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3011 break;
3012 case eCSR_AUTH_TYPE_CCKM_RSN:
3013 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3014 break;
3015 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3016 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3017 break;
3018 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3019 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3020 break;
3021 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3022 case eCSR_AUTH_TYPE_FAILED:
3023 case eCSR_AUTH_TYPE_NONE:
3024 default:
3025 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3026 break;
3027 }
3028 return ret_val;
3029}
3030
3031/**
3032 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3033 * vendor command
3034 * @dot11mode: dot11mode
3035 *
3036 * Return: Success(0) or reason code for failure
3037 */
3038static int hdd_convert_dot11mode(uint32_t dot11mode)
3039{
3040 uint32_t ret_val;
3041
3042 switch (dot11mode) {
3043 case eCSR_CFG_DOT11_MODE_11A:
3044 ret_val = QCA_WLAN_802_11_MODE_11A;
3045 break;
3046 case eCSR_CFG_DOT11_MODE_11B:
3047 ret_val = QCA_WLAN_802_11_MODE_11B;
3048 break;
3049 case eCSR_CFG_DOT11_MODE_11G:
3050 ret_val = QCA_WLAN_802_11_MODE_11G;
3051 break;
3052 case eCSR_CFG_DOT11_MODE_11N:
3053 ret_val = QCA_WLAN_802_11_MODE_11N;
3054 break;
3055 case eCSR_CFG_DOT11_MODE_11AC:
3056 ret_val = QCA_WLAN_802_11_MODE_11AC;
3057 break;
3058 case eCSR_CFG_DOT11_MODE_AUTO:
3059 case eCSR_CFG_DOT11_MODE_ABG:
3060 default:
3061 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3062 }
3063 return ret_val;
3064}
3065
3066/**
3067 * hdd_add_tx_bitrate() - add tx bitrate attribute
3068 * @skb: pointer to sk buff
3069 * @hdd_sta_ctx: pointer to hdd station context
3070 * @idx: attribute index
3071 *
3072 * Return: Success(0) or reason code for failure
3073 */
3074static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3075 hdd_station_ctx_t *hdd_sta_ctx,
3076 int idx)
3077{
3078 struct nlattr *nla_attr;
3079 uint32_t bitrate, bitrate_compat;
3080
3081 nla_attr = nla_nest_start(skb, idx);
3082 if (!nla_attr)
3083 goto fail;
3084 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3085 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3086
3087 /* report 16-bit bitrate only if we can */
3088 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3089 if (bitrate > 0 &&
3090 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3091 hdd_err("put fail");
3092 goto fail;
3093 }
3094 if (bitrate_compat > 0 &&
3095 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3096 hdd_err("put fail");
3097 goto fail;
3098 }
3099 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3100 hdd_sta_ctx->conn_info.txrate.nss)) {
3101 hdd_err("put fail");
3102 goto fail;
3103 }
3104 nla_nest_end(skb, nla_attr);
3105 return 0;
3106fail:
3107 return -EINVAL;
3108}
3109
3110/**
3111 * hdd_add_sta_info() - add station info attribute
3112 * @skb: pointer to sk buff
3113 * @hdd_sta_ctx: pointer to hdd station context
3114 * @idx: attribute index
3115 *
3116 * Return: Success(0) or reason code for failure
3117 */
3118static int32_t hdd_add_sta_info(struct sk_buff *skb,
3119 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3120{
3121 struct nlattr *nla_attr;
3122
3123 nla_attr = nla_nest_start(skb, idx);
3124 if (!nla_attr)
3125 goto fail;
3126 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3127 (hdd_sta_ctx->conn_info.signal + 100))) {
3128 hdd_err("put fail");
3129 goto fail;
3130 }
3131 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3132 goto fail;
3133 nla_nest_end(skb, nla_attr);
3134 return 0;
3135fail:
3136 return -EINVAL;
3137}
3138
3139/**
3140 * hdd_add_survey_info() - add survey info attribute
3141 * @skb: pointer to sk buff
3142 * @hdd_sta_ctx: pointer to hdd station context
3143 * @idx: attribute index
3144 *
3145 * Return: Success(0) or reason code for failure
3146 */
3147static int32_t hdd_add_survey_info(struct sk_buff *skb,
3148 hdd_station_ctx_t *hdd_sta_ctx,
3149 int idx)
3150{
3151 struct nlattr *nla_attr;
3152
3153 nla_attr = nla_nest_start(skb, idx);
3154 if (!nla_attr)
3155 goto fail;
3156 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3157 hdd_sta_ctx->conn_info.freq) ||
3158 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3159 (hdd_sta_ctx->conn_info.noise + 100))) {
3160 hdd_err("put fail");
3161 goto fail;
3162 }
3163 nla_nest_end(skb, nla_attr);
3164 return 0;
3165fail:
3166 return -EINVAL;
3167}
3168
3169/**
3170 * hdd_add_link_standard_info() - add link info attribute
3171 * @skb: pointer to sk buff
3172 * @hdd_sta_ctx: pointer to hdd station context
3173 * @idx: attribute index
3174 *
3175 * Return: Success(0) or reason code for failure
3176 */
3177static int32_t
3178hdd_add_link_standard_info(struct sk_buff *skb,
3179 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3180{
3181 struct nlattr *nla_attr;
3182
3183 nla_attr = nla_nest_start(skb, idx);
3184 if (!nla_attr)
3185 goto fail;
3186 if (nla_put(skb,
3187 NL80211_ATTR_SSID,
3188 hdd_sta_ctx->conn_info.SSID.SSID.length,
3189 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3190 hdd_err("put fail");
3191 goto fail;
3192 }
3193 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3194 goto fail;
3195 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3196 goto fail;
3197 nla_nest_end(skb, nla_attr);
3198 return 0;
3199fail:
3200 return -EINVAL;
3201}
3202
3203/**
3204 * hdd_add_ap_standard_info() - add ap info attribute
3205 * @skb: pointer to sk buff
3206 * @hdd_sta_ctx: pointer to hdd station context
3207 * @idx: attribute index
3208 *
3209 * Return: Success(0) or reason code for failure
3210 */
3211static int32_t
3212hdd_add_ap_standard_info(struct sk_buff *skb,
3213 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3214{
3215 struct nlattr *nla_attr;
3216
3217 nla_attr = nla_nest_start(skb, idx);
3218 if (!nla_attr)
3219 goto fail;
3220 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3221 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3222 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3223 &hdd_sta_ctx->conn_info.vht_caps)) {
3224 hdd_err("put fail");
3225 goto fail;
3226 }
3227 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3228 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3229 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3230 &hdd_sta_ctx->conn_info.ht_caps)) {
3231 hdd_err("put fail");
3232 goto fail;
3233 }
3234 nla_nest_end(skb, nla_attr);
3235 return 0;
3236fail:
3237 return -EINVAL;
3238}
3239
3240/**
3241 * hdd_get_station_info() - send BSS information to supplicant
3242 * @hdd_ctx: pointer to hdd context
3243 * @adapter: pointer to adapter
3244 *
3245 * Return: 0 if success else error status
3246 */
3247static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3248 hdd_adapter_t *adapter)
3249{
3250 struct sk_buff *skb = NULL;
3251 uint8_t *tmp_hs20 = NULL;
3252 uint32_t nl_buf_len;
3253 hdd_station_ctx_t *hdd_sta_ctx;
3254
3255 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3256
3257 nl_buf_len = NLMSG_HDRLEN;
3258 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3259 sizeof(hdd_sta_ctx->conn_info.freq) +
3260 sizeof(hdd_sta_ctx->conn_info.noise) +
3261 sizeof(hdd_sta_ctx->conn_info.signal) +
3262 (sizeof(uint32_t) * 2) +
3263 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3264 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3265 sizeof(hdd_sta_ctx->conn_info.authType) +
3266 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3267 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3268 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3269 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3270 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3271 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3272 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3273 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3274 1);
3275 }
3276 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3277 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3278 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3279 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3280
3281
3282 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3283 if (!skb) {
3284 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3285 return -ENOMEM;
3286 }
3287
3288 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3289 LINK_INFO_STANDARD_NL80211_ATTR)) {
3290 hdd_err("put fail");
3291 goto fail;
3292 }
3293 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3294 AP_INFO_STANDARD_NL80211_ATTR)) {
3295 hdd_err("put fail");
3296 goto fail;
3297 }
3298 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3299 hdd_sta_ctx->conn_info.roam_count) ||
3300 nla_put_u32(skb, INFO_AKM,
3301 hdd_convert_auth_type(
3302 hdd_sta_ctx->conn_info.authType)) ||
3303 nla_put_u32(skb, WLAN802_11_MODE,
3304 hdd_convert_dot11mode(
3305 hdd_sta_ctx->conn_info.dot11Mode))) {
3306 hdd_err("put fail");
3307 goto fail;
3308 }
3309 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3310 if (nla_put(skb, HT_OPERATION,
3311 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3312 &hdd_sta_ctx->conn_info.ht_operation)) {
3313 hdd_err("put fail");
3314 goto fail;
3315 }
3316 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3317 if (nla_put(skb, VHT_OPERATION,
3318 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3319 &hdd_sta_ctx->conn_info.vht_operation)) {
3320 hdd_err("put fail");
3321 goto fail;
3322 }
3323 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3324 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3325 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3326 tmp_hs20 + 1)) {
3327 hdd_err("put fail");
3328 goto fail;
3329 }
3330
3331 return cfg80211_vendor_cmd_reply(skb);
3332fail:
3333 if (skb)
3334 kfree_skb(skb);
3335 return -EINVAL;
3336}
3337
3338/**
3339 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3340 * @wiphy: corestack handler
3341 * @wdev: wireless device
3342 * @data: data
3343 * @data_len: data length
3344 *
3345 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3346 * Validate cmd attributes and send the station info to upper layers.
3347 *
3348 * Return: Success(0) or reason code for failure
3349 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303350static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303351__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3352 struct wireless_dev *wdev,
3353 const void *data,
3354 int data_len)
3355{
3356 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3357 struct net_device *dev = wdev->netdev;
3358 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3359 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3360 int32_t status;
3361
3362 ENTER_DEV(dev);
3363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3364 hdd_err("Command not allowed in FTM mode");
3365 status = -EPERM;
3366 goto out;
3367 }
3368
3369 status = wlan_hdd_validate_context(hdd_ctx);
3370 if (0 != status)
3371 goto out;
3372
3373
3374 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3375 data, data_len, NULL);
3376 if (status) {
3377 hdd_err("Invalid ATTR");
3378 goto out;
3379 }
3380
3381 /* Parse and fetch Command Type*/
3382 if (tb[STATION_INFO]) {
3383 status = hdd_get_station_info(hdd_ctx, adapter);
3384 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3385 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3386 } else {
3387 hdd_err("get station info cmd type failed");
3388 status = -EINVAL;
3389 goto out;
3390 }
3391 EXIT();
3392out:
3393 return status;
3394}
3395
3396/**
3397 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3398 * @wiphy: corestack handler
3399 * @wdev: wireless device
3400 * @data: data
3401 * @data_len: data length
3402 *
3403 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3404 * Validate cmd attributes and send the station info to upper layers.
3405 *
3406 * Return: Success(0) or reason code for failure
3407 */
3408static int32_t
3409hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3410 struct wireless_dev *wdev,
3411 const void *data,
3412 int data_len)
3413{
3414 int ret;
3415
3416 cds_ssr_protect(__func__);
3417 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3418 cds_ssr_unprotect(__func__);
3419
3420 return ret;
3421}
3422
3423/*
3424 * undef short names defined for get station command
3425 * used by __wlan_hdd_cfg80211_get_station_cmd()
3426 */
3427#undef STATION_INVALID
3428#undef STATION_INFO
3429#undef STATION_ASSOC_FAIL_REASON
3430#undef STATION_MAX
3431
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003432#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3433/**
3434 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3435 * @wiphy: pointer to wireless wiphy structure.
3436 * @wdev: pointer to wireless_dev structure.
3437 * @data: Pointer to the Key data
3438 * @data_len:Length of the data passed
3439 *
3440 * This is called when wlan driver needs to save the keys received via
3441 * vendor specific command.
3442 *
3443 * Return: Return the Success or Failure code.
3444 */
3445static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3446 struct wireless_dev *wdev,
3447 const void *data, int data_len)
3448{
3449 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3450 struct net_device *dev = wdev->netdev;
3451 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3452 hdd_context_t *hdd_ctx_ptr;
3453 int status;
3454
Jeff Johnson1f61b612016-02-12 16:28:33 -08003455 ENTER_DEV(dev);
3456
Anurag Chouhan6d760662016-02-20 16:05:43 +05303457 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 hdd_err("Command not allowed in FTM mode");
3459 return -EPERM;
3460 }
3461
3462 if ((data == NULL) || (data_len == 0) ||
3463 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003464 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465 return -EINVAL;
3466 }
3467
3468 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3469 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003470 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 return -EINVAL;
3472 }
3473
3474 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303475 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3478 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003479 true,
3480 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303481 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3482 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3484 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3485 return 0;
3486}
3487
3488/**
3489 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3490 * @wiphy: pointer to wireless wiphy structure.
3491 * @wdev: pointer to wireless_dev structure.
3492 * @data: Pointer to the Key data
3493 * @data_len:Length of the data passed
3494 *
3495 * This is called when wlan driver needs to save the keys received via
3496 * vendor specific command.
3497 *
3498 * Return: Return the Success or Failure code.
3499 */
3500static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3501 struct wireless_dev *wdev,
3502 const void *data, int data_len)
3503{
3504 int ret;
3505
3506 cds_ssr_protect(__func__);
3507 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3508 cds_ssr_unprotect(__func__);
3509
3510 return ret;
3511}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003512#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513
3514static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3515 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3516 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3517 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003518 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519};
3520
3521/**
3522 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3523 * @wiphy: pointer to wireless wiphy structure.
3524 * @wdev: pointer to wireless_dev structure.
3525 * @data: Pointer to the data to be passed via vendor interface
3526 * @data_len:Length of the data to be passed
3527 *
3528 * This is called when wlan driver needs to send wifi driver related info
3529 * (driver/fw version) to the user space application upon request.
3530 *
3531 * Return: Return the Success or Failure code.
3532 */
3533static int
3534__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3535 struct wireless_dev *wdev,
3536 const void *data, int data_len)
3537{
3538 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3539 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003540 tSirVersionString driver_version;
3541 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003544 struct sk_buff *reply_skb;
3545 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546
Jeff Johnson1f61b612016-02-12 16:28:33 -08003547 ENTER_DEV(wdev->netdev);
3548
Anurag Chouhan6d760662016-02-20 16:05:43 +05303549 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 hdd_err("Command not allowed in FTM mode");
3551 return -EPERM;
3552 }
3553
3554 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303555 if (status)
3556 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557
3558 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3559 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003560 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 return -EINVAL;
3562 }
3563
3564 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003565 hdd_err("Rcvd req for Driver version");
3566 strlcpy(driver_version, QWLAN_VERSIONSTR,
3567 sizeof(driver_version));
3568 skb_len += strlen(driver_version) + 1;
3569 count++;
3570 }
3571
3572 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3573 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3575 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003576 snprintf(firmware_version, sizeof(firmware_version),
3577 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3578 skb_len += strlen(firmware_version) + 1;
3579 count++;
3580 }
3581
3582 if (count == 0) {
3583 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 return -EINVAL;
3585 }
3586
Ryan Hsu7ac88852016-04-28 10:20:34 -07003587 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3588 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003591 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 return -ENOMEM;
3593 }
3594
Ryan Hsu7ac88852016-04-28 10:20:34 -07003595 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3596 if (nla_put_string(reply_skb,
3597 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3598 driver_version))
3599 goto error_nla_fail;
3600 }
3601
3602 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3603 if (nla_put_string(reply_skb,
3604 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3605 firmware_version))
3606 goto error_nla_fail;
3607 }
3608
3609 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3610 if (nla_put_u32(reply_skb,
3611 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3612 hdd_ctx->radio_index))
3613 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614 }
3615
3616 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003617
3618error_nla_fail:
3619 hdd_err("nla put fail");
3620 kfree_skb(reply_skb);
3621 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622}
3623
3624/**
3625 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3626 * @wiphy: pointer to wireless wiphy structure.
3627 * @wdev: pointer to wireless_dev structure.
3628 * @data: Pointer to the data to be passed via vendor interface
3629 * @data_len:Length of the data to be passed
3630 *
3631 * This is called when wlan driver needs to send wifi driver related info
3632 * (driver/fw version) to the user space application upon request.
3633 *
3634 * Return: Return the Success or Failure code.
3635 */
3636static int
3637wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3638 struct wireless_dev *wdev,
3639 const void *data, int data_len)
3640{
3641 int ret;
3642
3643 cds_ssr_protect(__func__);
3644 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3645 cds_ssr_unprotect(__func__);
3646
3647 return ret;
3648}
3649
3650/**
3651 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3652 * @wiphy: pointer to wireless wiphy structure.
3653 * @wdev: pointer to wireless_dev structure.
3654 * @data: Pointer to the data to be passed via vendor interface
3655 * @data_len:Length of the data to be passed
3656 *
3657 * This is called by userspace to know the supported logger features
3658 *
3659 * Return: Return the Success or Failure code.
3660 */
3661static int
3662__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3663 struct wireless_dev *wdev,
3664 const void *data, int data_len)
3665{
3666 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3667 int status;
3668 uint32_t features;
3669 struct sk_buff *reply_skb = NULL;
3670
Jeff Johnson1f61b612016-02-12 16:28:33 -08003671 ENTER_DEV(wdev->netdev);
3672
Anurag Chouhan6d760662016-02-20 16:05:43 +05303673 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674 hdd_err("Command not allowed in FTM mode");
3675 return -EPERM;
3676 }
3677
3678 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303679 if (status)
3680 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681
3682 features = 0;
3683
3684 if (hdd_is_memdump_supported())
3685 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3686 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3687 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3688 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3689
3690 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3691 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3692 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003693 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 return -ENOMEM;
3695 }
3696
Jeff Johnson020db452016-06-29 14:37:26 -07003697 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3699 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003700 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 kfree_skb(reply_skb);
3702 return -EINVAL;
3703 }
3704
3705 return cfg80211_vendor_cmd_reply(reply_skb);
3706}
3707
3708/**
3709 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3710 * @wiphy: pointer to wireless wiphy structure.
3711 * @wdev: pointer to wireless_dev structure.
3712 * @data: Pointer to the data to be passed via vendor interface
3713 * @data_len:Length of the data to be passed
3714 *
3715 * This is called by userspace to know the supported logger features
3716 *
3717 * Return: Return the Success or Failure code.
3718 */
3719static int
3720wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3721 struct wireless_dev *wdev,
3722 const void *data, int data_len)
3723{
3724 int ret;
3725
3726 cds_ssr_protect(__func__);
3727 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3728 data, data_len);
3729 cds_ssr_unprotect(__func__);
3730
3731 return ret;
3732}
3733
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003734#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735/**
3736 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3737 * @hdd_ctx_ptr: pointer to HDD Context.
3738 * @bssid: pointer to bssid of roamed AP.
3739 * @req_rsn_ie: Pointer to request RSN IE
3740 * @req_rsn_len: Length of the request RSN IE
3741 * @rsp_rsn_ie: Pointer to response RSN IE
3742 * @rsp_rsn_len: Length of the response RSN IE
3743 * @roam_info_ptr: Pointer to the roaming related information
3744 *
3745 * This is called when wlan driver needs to send the roaming and
3746 * authorization information after roaming.
3747 *
3748 * The information that would be sent is the request RSN IE, response
3749 * RSN IE and BSSID of the newly roamed AP.
3750 *
3751 * If the Authorized status is authenticated, then additional parameters
3752 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3753 * supplicant.
3754 *
3755 * The supplicant upon receiving this event would ignore the legacy
3756 * cfg80211_roamed call and use the entire information from this event.
3757 * The cfg80211_roamed should still co-exist since the kernel will
3758 * make use of the parameters even if the supplicant ignores it.
3759 *
3760 * Return: Return the Success or Failure code.
3761 */
3762int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3763 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3764 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3765{
3766 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003767 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 ENTER();
3769
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303770 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003773 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003774 !roam_info_ptr->roamSynchInProgress)
3775 return 0;
3776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3778 NULL,
3779 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3780 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3781 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003782 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3784 GFP_KERNEL);
3785
3786 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003787 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788 return -EINVAL;
3789 }
3790
3791 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3792 ETH_ALEN, bssid) ||
3793 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3794 req_rsn_len, req_rsn_ie) ||
3795 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3796 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003797 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 goto nla_put_failure;
3799 }
Jeff Johnson020db452016-06-29 14:37:26 -07003800 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 if (roam_info_ptr->synchAuthStatus ==
3802 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003803 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003804 if (nla_put_u8(skb,
3805 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3806 hdd_err("nla put fail");
3807 goto nla_put_failure;
3808 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003809 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3810 /* if FT or CCKM connection: dont send replay counter */
3811 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3812 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3813 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3814 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3815 nla_put(skb,
3816 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3817 SIR_REPLAY_CTR_LEN,
3818 roam_info_ptr->replay_ctr)) {
3819 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003820 hdd_err("failed to send replay counter.");
3821 goto nla_put_failure;
3822 }
3823 if (nla_put(skb,
3824 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3825 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3826 nla_put(skb,
3827 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3828 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3829 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 goto nla_put_failure;
3831 }
3832 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003833 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3835 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003836 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837 goto nla_put_failure;
3838 }
3839 }
3840
Jeff Johnson020db452016-06-29 14:37:26 -07003841 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003842 roam_info_ptr->subnet_change_status);
3843
3844 /*
3845 * Add subnet change status if subnet has changed
3846 * 0 = unchanged
3847 * 1 = changed
3848 * 2 = unknown
3849 */
3850 if (roam_info_ptr->subnet_change_status) {
3851 if (nla_put_u8(skb,
3852 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3853 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003854 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003855 goto nla_put_failure;
3856 }
3857 }
3858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 cfg80211_vendor_event(skb, GFP_KERNEL);
3860 return 0;
3861
3862nla_put_failure:
3863 kfree_skb(skb);
3864 return -EINVAL;
3865}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003866#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867
3868static const struct nla_policy
3869wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3870
3871 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3872 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3873 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303874 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303875 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3876 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877};
3878
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303880 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3881 *
3882 * @adapter: Pointer to HDD adapter
3883 * @ie_data: Pointer to Scan IEs buffer
3884 * @ie_len: Length of Scan IEs
3885 *
3886 * Return: 0 on success; error number otherwise
3887 */
3888static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3889 uint8_t *ie_data, uint8_t ie_len)
3890{
3891 hdd_scaninfo_t *scan_info = NULL;
3892 scan_info = &adapter->scan_info;
3893
3894 if (scan_info->default_scan_ies) {
3895 qdf_mem_free(scan_info->default_scan_ies);
3896 scan_info->default_scan_ies = NULL;
3897 }
3898
3899 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3900 if (!scan_info->default_scan_ies)
3901 return -ENOMEM;
3902
3903 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3904 scan_info->default_scan_ies_len = ie_len;
3905 return 0;
3906}
3907
3908/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3910 * vendor command
3911 *
3912 * @wiphy: wiphy device pointer
3913 * @wdev: wireless device pointer
3914 * @data: Vendor command data buffer
3915 * @data_len: Buffer length
3916 *
3917 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3918 *
3919 * Return: Error code.
3920 */
3921static int
3922__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3923 struct wireless_dev *wdev,
3924 const void *data,
3925 int data_len)
3926{
3927 struct net_device *dev = wdev->netdev;
3928 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3930 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3931 int ret_val = 0;
3932 u32 modulated_dtim;
3933 u16 stats_avg_factor;
3934 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303935 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003936 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003937 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303938 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303939 int attr_len;
3940 int access_policy = 0;
3941 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3942 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303943 uint16_t scan_ie_len = 0;
3944 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303945 struct sir_set_tx_rx_aggregation_size request;
3946 QDF_STATUS qdf_status;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303947
Jeff Johnson1f61b612016-02-12 16:28:33 -08003948 ENTER_DEV(dev);
3949
Anurag Chouhan6d760662016-02-20 16:05:43 +05303950 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 hdd_err("Command not allowed in FTM mode");
3952 return -EPERM;
3953 }
3954
3955 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303956 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958
3959 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3960 data, data_len,
3961 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003962 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 return -EINVAL;
3964 }
3965
Krunal Sonie3531942016-04-12 17:43:53 -07003966 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3967 ftm_capab = nla_get_u32(tb[
3968 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3969 hdd_ctx->config->fine_time_meas_cap =
3970 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3971 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303972 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003973 hdd_ctx->config->fine_time_meas_cap);
3974 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3975 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3976 hdd_ctx->config->fine_time_meas_cap);
3977 }
3978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3980 modulated_dtim = nla_get_u32(
3981 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3982
3983 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3984 adapter->sessionId,
3985 modulated_dtim);
3986
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303987 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 ret_val = -EPERM;
3989 }
3990
Kapil Gupta6213c012016-09-02 19:39:09 +05303991 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
3992 qpower = nla_get_u8(
3993 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
3994 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
3995 ret_val = -EINVAL;
3996 }
3997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3999 stats_avg_factor = nla_get_u16(
4000 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4001 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4002 adapter->sessionId,
4003 stats_avg_factor);
4004
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304005 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 ret_val = -EPERM;
4007 }
4008
4009
4010 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4011 guard_time = nla_get_u32(
4012 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4013 status = sme_configure_guard_time(hdd_ctx->hHal,
4014 adapter->sessionId,
4015 guard_time);
4016
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304017 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018 ret_val = -EPERM;
4019 }
4020
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304021 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4022 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4023 attr_len = nla_len(
4024 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4025 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4026 hdd_info("Invalid value. attr_len %d",
4027 attr_len);
4028 return -EINVAL;
4029 }
4030
4031 nla_memcpy(&vendor_ie,
4032 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4033 attr_len);
4034 vendor_ie_present = true;
4035 hdd_info("Access policy vendor ie present.attr_len %d",
4036 attr_len);
4037 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4038 &vendor_ie[0], attr_len);
4039 }
4040
4041 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4042 access_policy = (int) nla_get_u32(
4043 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4044 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4045 (access_policy >
4046 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4047 hdd_info("Invalid value. access_policy %d",
4048 access_policy);
4049 return -EINVAL;
4050 }
4051 access_policy_present = true;
4052 hdd_info("Access policy present. access_policy %d",
4053 access_policy);
4054 }
4055
4056 if (vendor_ie_present && access_policy_present) {
4057 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4058 access_policy =
4059 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
4060 } else {
4061 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
4062 }
4063
4064 hdd_info("calling sme_update_access_policy_vendor_ie");
4065 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4066 adapter->sessionId, &vendor_ie[0],
4067 access_policy);
4068 if (QDF_STATUS_SUCCESS != status) {
4069 hdd_info("Failed to set vendor ie and access policy.");
4070 return -EINVAL;
4071 }
4072 }
4073
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304074 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4075 set_value = nla_get_u8(
4076 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4077 hdd_info("set_value: %d", set_value);
4078 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4079 }
4080
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304081 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4082 scan_ie_len = nla_len(
4083 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4084 hdd_info("Received default scan IE of len %d session %d device mode %d",
4085 scan_ie_len, adapter->sessionId,
4086 adapter->device_mode);
4087 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4088 scan_ie = (uint8_t *) nla_data(tb
4089 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304090
4091 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4092 scan_ie_len))
4093 hdd_err("Failed to save default scan IEs");
4094
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304095 if (adapter->device_mode == QDF_STA_MODE) {
4096 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4097 adapter->sessionId, scan_ie,
4098 scan_ie_len);
4099 if (QDF_STATUS_SUCCESS != status)
4100 ret_val = -EPERM;
4101 }
4102 } else
4103 ret_val = -EPERM;
4104 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304105
4106 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4107 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4108 /* if one is specified, both must be specified */
4109 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4110 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4111 hdd_err("Both TX and RX MPDU Aggregation required");
4112 return -EINVAL;
4113 }
4114
4115 request.tx_aggregation_size = nla_get_u8(
4116 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4117 request.rx_aggregation_size = nla_get_u8(
4118 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4119 request.vdev_id = adapter->sessionId;
4120
4121 if (request.tx_aggregation_size >=
4122 CFG_TX_AGGREGATION_SIZE_MIN &&
4123 request.tx_aggregation_size <=
4124 CFG_TX_AGGREGATION_SIZE_MAX &&
4125 request.rx_aggregation_size >=
4126 CFG_RX_AGGREGATION_SIZE_MIN &&
4127 request.rx_aggregation_size <=
4128 CFG_RX_AGGREGATION_SIZE_MAX) {
4129 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4130 if (qdf_status != QDF_STATUS_SUCCESS) {
4131 hdd_err("failed to set aggr sizes err %d",
4132 qdf_status);
4133 ret_val = -EPERM;
4134 }
4135 } else {
4136 hdd_err("TX %d RX %d MPDU aggr size not in range",
4137 request.tx_aggregation_size,
4138 request.rx_aggregation_size);
4139 ret_val = -EINVAL;
4140 }
4141 }
4142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143 return ret_val;
4144}
4145
4146/**
4147 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4148 * vendor command
4149 *
4150 * @wiphy: wiphy device pointer
4151 * @wdev: wireless device pointer
4152 * @data: Vendor command data buffer
4153 * @data_len: Buffer length
4154 *
4155 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4156 *
4157 * Return: EOK or other error codes.
4158 */
4159static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4160 struct wireless_dev *wdev,
4161 const void *data,
4162 int data_len)
4163{
4164 int ret;
4165
4166 cds_ssr_protect(__func__);
4167 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4168 data, data_len);
4169 cds_ssr_unprotect(__func__);
4170
4171 return ret;
4172}
4173
4174static const struct
4175nla_policy
4176qca_wlan_vendor_wifi_logger_start_policy
4177[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4178 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4179 = {.type = NLA_U32 },
4180 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4181 = {.type = NLA_U32 },
4182 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4183 = {.type = NLA_U32 },
4184};
4185
4186/**
4187 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4188 * or disable the collection of packet statistics from the firmware
4189 * @wiphy: WIPHY structure pointer
4190 * @wdev: Wireless device structure pointer
4191 * @data: Pointer to the data received
4192 * @data_len: Length of the data received
4193 *
4194 * This function enables or disables the collection of packet statistics from
4195 * the firmware
4196 *
4197 * Return: 0 on success and errno on failure
4198 */
4199static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4200 struct wireless_dev *wdev,
4201 const void *data,
4202 int data_len)
4203{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304204 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4206 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4207 struct sir_wifi_start_log start_log;
4208
Jeff Johnson1f61b612016-02-12 16:28:33 -08004209 ENTER_DEV(wdev->netdev);
4210
Anurag Chouhan6d760662016-02-20 16:05:43 +05304211 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212 hdd_err("Command not allowed in FTM mode");
4213 return -EPERM;
4214 }
4215
4216 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304217 if (status)
4218 return status;
4219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004220
4221 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4222 data, data_len,
4223 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004224 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 return -EINVAL;
4226 }
4227
4228 /* Parse and fetch ring id */
4229 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004230 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231 return -EINVAL;
4232 }
4233 start_log.ring_id = nla_get_u32(
4234 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004235 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236
4237 /* Parse and fetch verbose level */
4238 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004239 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 return -EINVAL;
4241 }
4242 start_log.verbose_level = nla_get_u32(
4243 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004244 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245
4246 /* Parse and fetch flag */
4247 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004248 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004249 return -EINVAL;
4250 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304251 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304253 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254
4255 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4256
4257 if (start_log.ring_id == RING_ID_WAKELOCK) {
4258 /* Start/stop wakelock events */
4259 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4260 cds_set_wakelock_logging(true);
4261 else
4262 cds_set_wakelock_logging(false);
4263 return 0;
4264 }
4265
4266 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304267 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004268 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 status);
4270 return -EINVAL;
4271 }
4272 return 0;
4273}
4274
4275/**
4276 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4277 * or disable the collection of packet statistics from the firmware
4278 * @wiphy: WIPHY structure pointer
4279 * @wdev: Wireless device structure pointer
4280 * @data: Pointer to the data received
4281 * @data_len: Length of the data received
4282 *
4283 * This function is used to enable or disable the collection of packet
4284 * statistics from the firmware
4285 *
4286 * Return: 0 on success and errno on failure
4287 */
4288static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4289 struct wireless_dev *wdev,
4290 const void *data,
4291 int data_len)
4292{
4293 int ret = 0;
4294
4295 cds_ssr_protect(__func__);
4296 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4297 wdev, data, data_len);
4298 cds_ssr_unprotect(__func__);
4299
4300 return ret;
4301}
4302
4303static const struct
4304nla_policy
4305qca_wlan_vendor_wifi_logger_get_ring_data_policy
4306[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4307 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4308 = {.type = NLA_U32 },
4309};
4310
4311/**
4312 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4313 * @wiphy: WIPHY structure pointer
4314 * @wdev: Wireless device structure pointer
4315 * @data: Pointer to the data received
4316 * @data_len: Length of the data received
4317 *
4318 * This function is used to flush or retrieve the per packet statistics from
4319 * the driver
4320 *
4321 * Return: 0 on success and errno on failure
4322 */
4323static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4324 struct wireless_dev *wdev,
4325 const void *data,
4326 int data_len)
4327{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304328 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 uint32_t ring_id;
4330 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4331 struct nlattr *tb
4332 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4333
Jeff Johnson1f61b612016-02-12 16:28:33 -08004334 ENTER_DEV(wdev->netdev);
4335
Anurag Chouhan6d760662016-02-20 16:05:43 +05304336 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004337 hdd_err("Command not allowed in FTM mode");
4338 return -EPERM;
4339 }
4340
4341 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304342 if (status)
4343 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344
4345 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4346 data, data_len,
4347 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004348 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 return -EINVAL;
4350 }
4351
4352 /* Parse and fetch ring id */
4353 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004354 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 return -EINVAL;
4356 }
4357
4358 ring_id = nla_get_u32(
4359 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4360
4361 if (ring_id == RING_ID_PER_PACKET_STATS) {
4362 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004363 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304364 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4365 /*
4366 * As part of DRIVER ring ID, flush both driver and fw logs.
4367 * For other Ring ID's driver doesn't have any rings to flush
4368 */
4369 hdd_notice("Bug report triggered by framework");
4370
4371 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4372 WLAN_LOG_INDICATOR_FRAMEWORK,
4373 WLAN_LOG_REASON_CODE_UNUSED,
4374 true, false);
4375 if (QDF_STATUS_SUCCESS != status) {
4376 hdd_err("Failed to trigger bug report");
4377 return -EINVAL;
4378 }
4379 } else {
4380 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4381 WLAN_LOG_INDICATOR_FRAMEWORK,
4382 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 return 0;
4385}
4386
4387/**
4388 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4389 * @wiphy: WIPHY structure pointer
4390 * @wdev: Wireless device structure pointer
4391 * @data: Pointer to the data received
4392 * @data_len: Length of the data received
4393 *
4394 * This function is used to flush or retrieve the per packet statistics from
4395 * the driver
4396 *
4397 * Return: 0 on success and errno on failure
4398 */
4399static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4400 struct wireless_dev *wdev,
4401 const void *data,
4402 int data_len)
4403{
4404 int ret = 0;
4405
4406 cds_ssr_protect(__func__);
4407 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4408 wdev, data, data_len);
4409 cds_ssr_unprotect(__func__);
4410
4411 return ret;
4412}
4413
4414#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4415/**
4416 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4417 * @hdd_ctx: HDD context
4418 * @request_id: [input] request id
4419 * @pattern_id: [output] pattern id
4420 *
4421 * This function loops through request id to pattern id array
4422 * if the slot is available, store the request id and return pattern id
4423 * if entry exists, return the pattern id
4424 *
4425 * Return: 0 on success and errno on failure
4426 */
4427static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4428 uint32_t request_id,
4429 uint8_t *pattern_id)
4430{
4431 uint32_t i;
4432
4433 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4434 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4435 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4436 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4437 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4438 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4439 return 0;
4440 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4441 request_id) {
4442 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4443 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4444 return 0;
4445 }
4446 }
4447 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4448 return -EINVAL;
4449}
4450
4451/**
4452 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4453 * @hdd_ctx: HDD context
4454 * @request_id: [input] request id
4455 * @pattern_id: [output] pattern id
4456 *
4457 * This function loops through request id to pattern id array
4458 * reset request id to 0 (slot available again) and
4459 * return pattern id
4460 *
4461 * Return: 0 on success and errno on failure
4462 */
4463static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4464 uint32_t request_id,
4465 uint8_t *pattern_id)
4466{
4467 uint32_t i;
4468
4469 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4470 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4471 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4472 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4473 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4474 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4475 return 0;
4476 }
4477 }
4478 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4479 return -EINVAL;
4480}
4481
4482
4483/*
4484 * define short names for the global vendor params
4485 * used by __wlan_hdd_cfg80211_offloaded_packets()
4486 */
4487#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4488#define PARAM_REQUEST_ID \
4489 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4490#define PARAM_CONTROL \
4491 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4492#define PARAM_IP_PACKET \
4493 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4494#define PARAM_SRC_MAC_ADDR \
4495 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4496#define PARAM_DST_MAC_ADDR \
4497 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4498#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4499
4500/**
4501 * wlan_hdd_add_tx_ptrn() - add tx pattern
4502 * @adapter: adapter pointer
4503 * @hdd_ctx: hdd context
4504 * @tb: nl attributes
4505 *
4506 * This function reads the NL attributes and forms a AddTxPtrn message
4507 * posts it to SME.
4508 *
4509 */
4510static int
4511wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4512 struct nlattr **tb)
4513{
4514 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304515 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004516 uint32_t request_id, ret, len;
4517 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304518 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519 uint16_t eth_type = htons(ETH_P_IP);
4520
4521 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004522 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 return -ENOTSUPP;
4524 }
4525
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304526 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004528 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 return -ENOMEM;
4530 }
4531
4532 /* Parse and fetch request Id */
4533 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004534 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535 goto fail;
4536 }
4537
4538 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4539 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004540 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004541 return -EINVAL;
4542 }
Jeff Johnson77848112016-06-29 14:52:06 -07004543 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004544
4545 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004546 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004547 goto fail;
4548 }
4549 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004550 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004552 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553 goto fail;
4554 }
4555
4556 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004557 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 goto fail;
4559 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004560 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304561 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004562 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004563 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564
Anurag Chouhanc5548422016-02-24 18:33:27 +05304565 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004566 &adapter->macAddressCurrent)) {
4567 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568 goto fail;
4569 }
4570
4571 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004572 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 goto fail;
4574 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304575 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004576 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 MAC_ADDR_ARRAY(dst_addr.bytes));
4578
4579 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004580 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 goto fail;
4582 }
4583 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004584 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585
4586 if (add_req->ucPtrnSize < 0 ||
4587 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4588 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004589 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590 add_req->ucPtrnSize);
4591 goto fail;
4592 }
4593
4594 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304595 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304596 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304597 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304598 QDF_MAC_ADDR_SIZE);
4599 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304600 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 len += 2;
4602
4603 /*
4604 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4605 * ------------------------------------------------------------
4606 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4607 * ------------------------------------------------------------
4608 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304609 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 nla_data(tb[PARAM_IP_PACKET]),
4611 add_req->ucPtrnSize);
4612 add_req->ucPtrnSize += len;
4613
4614 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4615 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004616 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617 goto fail;
4618 }
4619 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004620 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621
4622 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304623 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004624 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 goto fail;
4626 }
4627
4628 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304629 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 return 0;
4631
4632fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304633 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634 return -EINVAL;
4635}
4636
4637/**
4638 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4639 * @adapter: adapter pointer
4640 * @hdd_ctx: hdd context
4641 * @tb: nl attributes
4642 *
4643 * This function reads the NL attributes and forms a DelTxPtrn message
4644 * posts it to SME.
4645 *
4646 */
4647static int
4648wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4649 struct nlattr **tb)
4650{
4651 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304652 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653 uint32_t request_id, ret;
4654 uint8_t pattern_id = 0;
4655
4656 /* Parse and fetch request Id */
4657 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004658 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659 return -EINVAL;
4660 }
4661 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4662 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004663 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 return -EINVAL;
4665 }
4666
4667 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4668 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004669 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004670 return -EINVAL;
4671 }
4672
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304673 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004675 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676 return -ENOMEM;
4677 }
4678
Anurag Chouhanc5548422016-02-24 18:33:27 +05304679 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004680 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004682 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 request_id, del_req->ucPtrnId);
4684
4685 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304686 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004687 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 goto fail;
4689 }
4690
4691 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304692 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 return 0;
4694
4695fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304696 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 return -EINVAL;
4698}
4699
4700
4701/**
4702 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4703 * @wiphy: Pointer to wireless phy
4704 * @wdev: Pointer to wireless device
4705 * @data: Pointer to data
4706 * @data_len: Data length
4707 *
4708 * Return: 0 on success, negative errno on failure
4709 */
4710static int
4711__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4712 struct wireless_dev *wdev,
4713 const void *data,
4714 int data_len)
4715{
4716 struct net_device *dev = wdev->netdev;
4717 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4718 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4719 struct nlattr *tb[PARAM_MAX + 1];
4720 uint8_t control;
4721 int ret;
4722 static const struct nla_policy policy[PARAM_MAX + 1] = {
4723 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4724 [PARAM_CONTROL] = { .type = NLA_U32 },
4725 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304726 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304728 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729 [PARAM_PERIOD] = { .type = NLA_U32 },
4730 };
4731
Jeff Johnson1f61b612016-02-12 16:28:33 -08004732 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733
Anurag Chouhan6d760662016-02-20 16:05:43 +05304734 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004735 hdd_err("Command not allowed in FTM mode");
4736 return -EPERM;
4737 }
4738
4739 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304740 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004742
4743 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004744 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004745 return -ENOTSUPP;
4746 }
4747
4748 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004749 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750 return -EINVAL;
4751 }
4752
4753 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004754 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 return -EINVAL;
4756 }
4757 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004758 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004759
4760 if (control == WLAN_START_OFFLOADED_PACKETS)
4761 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4762 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4763 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4764 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004765 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766 return -EINVAL;
4767 }
4768}
4769
4770/*
4771 * done with short names for the global vendor params
4772 * used by __wlan_hdd_cfg80211_offloaded_packets()
4773 */
4774#undef PARAM_MAX
4775#undef PARAM_REQUEST_ID
4776#undef PARAM_CONTROL
4777#undef PARAM_IP_PACKET
4778#undef PARAM_SRC_MAC_ADDR
4779#undef PARAM_DST_MAC_ADDR
4780#undef PARAM_PERIOD
4781
4782/**
4783 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4784 * @wiphy: wiphy structure pointer
4785 * @wdev: Wireless device structure pointer
4786 * @data: Pointer to the data received
4787 * @data_len: Length of @data
4788 *
4789 * Return: 0 on success; errno on failure
4790 */
4791static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4792 struct wireless_dev *wdev,
4793 const void *data,
4794 int data_len)
4795{
4796 int ret = 0;
4797
4798 cds_ssr_protect(__func__);
4799 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4800 wdev, data, data_len);
4801 cds_ssr_unprotect(__func__);
4802
4803 return ret;
4804}
4805#endif
4806
4807/*
4808 * define short names for the global vendor params
4809 * used by __wlan_hdd_cfg80211_monitor_rssi()
4810 */
4811#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4812#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4813#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4814#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4815#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4816
4817/**
4818 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4819 * @wiphy: Pointer to wireless phy
4820 * @wdev: Pointer to wireless device
4821 * @data: Pointer to data
4822 * @data_len: Data length
4823 *
4824 * Return: 0 on success, negative errno on failure
4825 */
4826static int
4827__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4828 struct wireless_dev *wdev,
4829 const void *data,
4830 int data_len)
4831{
4832 struct net_device *dev = wdev->netdev;
4833 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4834 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4835 struct nlattr *tb[PARAM_MAX + 1];
4836 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304837 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 int ret;
4839 uint32_t control;
4840 static const struct nla_policy policy[PARAM_MAX + 1] = {
4841 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4842 [PARAM_CONTROL] = { .type = NLA_U32 },
4843 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4844 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4845 };
4846
Jeff Johnson1f61b612016-02-12 16:28:33 -08004847 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848
4849 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304850 if (ret)
4851 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852
4853 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004854 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855 return -ENOTSUPP;
4856 }
4857
4858 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004859 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 return -EINVAL;
4861 }
4862
4863 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004864 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 return -EINVAL;
4866 }
4867
4868 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004869 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 return -EINVAL;
4871 }
4872
4873 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4874 req.session_id = adapter->sessionId;
4875 control = nla_get_u32(tb[PARAM_CONTROL]);
4876
4877 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4878 req.control = true;
4879 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004880 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 return -EINVAL;
4882 }
4883
4884 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004885 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 return -EINVAL;
4887 }
4888
4889 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4890 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4891
4892 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004893 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004894 req.min_rssi, req.max_rssi);
4895 return -EINVAL;
4896 }
Jeff Johnson77848112016-06-29 14:52:06 -07004897 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898 req.min_rssi, req.max_rssi);
4899
4900 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4901 req.control = false;
4902 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004903 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904 return -EINVAL;
4905 }
Jeff Johnson77848112016-06-29 14:52:06 -07004906 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 req.request_id, req.session_id, req.control);
4908
4909 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304910 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004911 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 return -EINVAL;
4913 }
4914
4915 return 0;
4916}
4917
4918/*
4919 * done with short names for the global vendor params
4920 * used by __wlan_hdd_cfg80211_monitor_rssi()
4921 */
4922#undef PARAM_MAX
4923#undef PARAM_CONTROL
4924#undef PARAM_REQUEST_ID
4925#undef PARAM_MAX_RSSI
4926#undef PARAM_MIN_RSSI
4927
4928/**
4929 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4930 * @wiphy: wiphy structure pointer
4931 * @wdev: Wireless device structure pointer
4932 * @data: Pointer to the data received
4933 * @data_len: Length of @data
4934 *
4935 * Return: 0 on success; errno on failure
4936 */
4937static int
4938wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4939 const void *data, int data_len)
4940{
4941 int ret;
4942
4943 cds_ssr_protect(__func__);
4944 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4945 cds_ssr_unprotect(__func__);
4946
4947 return ret;
4948}
4949
4950/**
4951 * hdd_rssi_threshold_breached() - rssi breached NL event
4952 * @hddctx: HDD context
4953 * @data: rssi breached event data
4954 *
4955 * This function reads the rssi breached event %data and fill in the skb with
4956 * NL attributes and send up the NL event.
4957 *
4958 * Return: none
4959 */
4960void hdd_rssi_threshold_breached(void *hddctx,
4961 struct rssi_breach_event *data)
4962{
4963 hdd_context_t *hdd_ctx = hddctx;
4964 struct sk_buff *skb;
4965
4966 ENTER();
4967
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304968 if (wlan_hdd_validate_context(hdd_ctx))
4969 return;
4970 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07004971 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004972 return;
4973 }
4974
4975 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4976 NULL,
4977 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4978 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4979 GFP_KERNEL);
4980
4981 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07004982 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983 return;
4984 }
4985
Jeff Johnson77848112016-06-29 14:52:06 -07004986 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07004988 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004989 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4990
4991 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4992 data->request_id) ||
4993 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4994 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4995 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4996 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004997 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004998 goto fail;
4999 }
5000
5001 cfg80211_vendor_event(skb, GFP_KERNEL);
5002 return;
5003
5004fail:
5005 kfree_skb(skb);
5006 return;
5007}
5008
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305009static const struct nla_policy
5010ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5011 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5012};
5013
5014/**
5015 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5016 * @wiphy: Pointer to wireless phy
5017 * @wdev: Pointer to wireless device
5018 * @data: Pointer to data
5019 * @data_len: Length of @data
5020 *
5021 * Return: 0 on success, negative errno on failure
5022 */
5023static int
5024__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5025 struct wireless_dev *wdev,
5026 const void *data, int data_len)
5027{
5028 int status;
5029 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5030 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005031 struct net_device *dev = wdev->netdev;
5032 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305033
5034 ENTER_DEV(wdev->netdev);
5035
5036 status = wlan_hdd_validate_context(pHddCtx);
5037 if (0 != status)
5038 return status;
5039 if (!pHddCtx->config->fhostNSOffload) {
5040 hdd_err("ND Offload not supported");
5041 return -EINVAL;
5042 }
5043
5044 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5045 (struct nlattr *)data,
5046 data_len, ns_offload_set_policy)) {
5047 hdd_err("nla_parse failed");
5048 return -EINVAL;
5049 }
5050
5051 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5052 hdd_err("ND Offload flag attribute not present");
5053 return -EINVAL;
5054 }
5055
5056 pHddCtx->ns_offload_enable =
5057 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5058
Dustin Brownd8279d22016-09-07 14:52:57 -07005059 /* update ns offload in case it is already enabled/disabled */
5060 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5061
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305062 return 0;
5063}
5064
5065/**
5066 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5067 * @wiphy: pointer to wireless wiphy structure.
5068 * @wdev: pointer to wireless_dev structure.
5069 * @data: Pointer to the data to be passed via vendor interface
5070 * @data_len:Length of the data to be passed
5071 *
5072 * Return: Return the Success or Failure code.
5073 */
5074static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5075 struct wireless_dev *wdev,
5076 const void *data, int data_len)
5077{
5078 int ret;
5079
5080 cds_ssr_protect(__func__);
5081 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5082 cds_ssr_unprotect(__func__);
5083
5084 return ret;
5085}
5086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5088 * @wiphy: Pointer to wireless phy
5089 * @wdev: Pointer to wireless device
5090 * @data: Pointer to data
5091 * @data_len: Data length
5092 *
5093 * This function return the preferred frequency list generated by the policy
5094 * manager.
5095 *
5096 * Return: success or failure code
5097 */
5098static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5099 struct wireless_dev
5100 *wdev, const void *data,
5101 int data_len)
5102{
5103 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5104 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305105 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305106 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005107 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305108 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005109 enum cds_con_mode intf_mode;
5110 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5111 struct sk_buff *reply_skb;
5112
Jeff Johnson1f61b612016-02-12 16:28:33 -08005113 ENTER_DEV(wdev->netdev);
5114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005115 ret = wlan_hdd_validate_context(hdd_ctx);
5116 if (ret)
5117 return -EINVAL;
5118
5119 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5120 data, data_len, NULL)) {
5121 hdd_err("Invalid ATTR");
5122 return -EINVAL;
5123 }
5124
5125 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5126 hdd_err("attr interface type failed");
5127 return -EINVAL;
5128 }
5129
5130 intf_mode = nla_get_u32(tb
5131 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5132
5133 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5134 hdd_err("Invalid interface type");
5135 return -EINVAL;
5136 }
5137
5138 hdd_debug("Userspace requested pref freq list");
5139
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305140 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5141 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305142 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005143 hdd_err("Get pcl failed");
5144 return -EINVAL;
5145 }
5146
5147 /* convert channel number to frequency */
5148 for (i = 0; i < pcl_len; i++) {
5149 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5150 freq_list[i] =
5151 ieee80211_channel_to_frequency(pcl[i],
5152 IEEE80211_BAND_2GHZ);
5153 else
5154 freq_list[i] =
5155 ieee80211_channel_to_frequency(pcl[i],
5156 IEEE80211_BAND_5GHZ);
5157 }
5158
5159 /* send the freq_list back to supplicant */
5160 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5161 sizeof(u32) *
5162 pcl_len +
5163 NLMSG_HDRLEN);
5164
5165 if (!reply_skb) {
5166 hdd_err("Allocate reply_skb failed");
5167 return -EINVAL;
5168 }
5169
5170 if (nla_put_u32(reply_skb,
5171 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5172 intf_mode) ||
5173 nla_put(reply_skb,
5174 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5175 sizeof(uint32_t) * pcl_len,
5176 freq_list)) {
5177 hdd_err("nla put fail");
5178 kfree_skb(reply_skb);
5179 return -EINVAL;
5180 }
5181
5182 return cfg80211_vendor_cmd_reply(reply_skb);
5183}
5184
5185/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5186 * @wiphy: Pointer to wireless phy
5187 * @wdev: Pointer to wireless device
5188 * @data: Pointer to data
5189 * @data_len: Data length
5190 *
5191 * This function return the preferred frequency list generated by the policy
5192 * manager.
5193 *
5194 * Return: success or failure code
5195 */
5196static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5197 struct wireless_dev
5198 *wdev, const void *data,
5199 int data_len)
5200{
5201 int ret = 0;
5202
5203 cds_ssr_protect(__func__);
5204 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5205 data, data_len);
5206 cds_ssr_unprotect(__func__);
5207
5208 return ret;
5209}
5210
5211/**
5212 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5213 * @wiphy: Pointer to wireless phy
5214 * @wdev: Pointer to wireless device
5215 * @data: Pointer to data
5216 * @data_len: Data length
5217 *
5218 * Return: 0 on success, negative errno on failure
5219 */
5220static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5221 struct wireless_dev *wdev,
5222 const void *data,
5223 int data_len)
5224{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305225 struct net_device *ndev = wdev->netdev;
5226 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5228 int ret = 0;
5229 enum cds_con_mode intf_mode;
5230 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5231 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232
Jeff Johnson1f61b612016-02-12 16:28:33 -08005233 ENTER_DEV(ndev);
5234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235 ret = wlan_hdd_validate_context(hdd_ctx);
5236 if (ret)
5237 return ret;
5238
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5240 data, data_len, NULL)) {
5241 hdd_err("Invalid ATTR");
5242 return -EINVAL;
5243 }
5244
5245 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5246 hdd_err("attr interface type failed");
5247 return -EINVAL;
5248 }
5249
5250 intf_mode = nla_get_u32(tb
5251 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5252
5253 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5254 hdd_err("Invalid interface type");
5255 return -EINVAL;
5256 }
5257
5258 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5259 hdd_err("attr probable freq failed");
5260 return -EINVAL;
5261 }
5262
5263 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5264 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5265
5266 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005267 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268 channel_hint, HW_MODE_20_MHZ)) {
5269 hdd_err("Set channel hint failed due to concurrency check");
5270 return -EINVAL;
5271 }
5272
Krunal Soni09e55032016-06-07 10:06:55 -07005273 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5274 hdd_warn("Remain On Channel Pending");
5275
Krunal Soni3091bcc2016-06-23 12:28:21 -07005276 ret = qdf_reset_connection_update();
5277 if (!QDF_IS_STATUS_SUCCESS(ret))
5278 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005279
Krunal Soni3091bcc2016-06-23 12:28:21 -07005280 ret = cds_current_connections_update(adapter->sessionId,
5281 channel_hint,
5282 SIR_UPDATE_REASON_SET_OPER_CHAN);
5283 if (QDF_STATUS_E_FAILURE == ret) {
5284 /* return in the failure case */
5285 hdd_err("ERROR: connections update failed!!");
5286 return -EINVAL;
5287 }
5288
5289 if (QDF_STATUS_SUCCESS == ret) {
5290 /*
5291 * Success is the only case for which we expect hw mode
5292 * change to take place, hence we need to wait.
5293 * For any other return value it should be a pass
5294 * through
5295 */
5296 ret = qdf_wait_for_connection_update();
5297 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5298 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005299 return -EINVAL;
5300 }
5301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005302 }
5303
5304 return 0;
5305}
5306
5307/**
5308 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5309 * @wiphy: Pointer to wireless phy
5310 * @wdev: Pointer to wireless device
5311 * @data: Pointer to data
5312 * @data_len: Data length
5313 *
5314 * Return: 0 on success, negative errno on failure
5315 */
5316static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5317 struct wireless_dev *wdev,
5318 const void *data,
5319 int data_len)
5320{
5321 int ret = 0;
5322
5323 cds_ssr_protect(__func__);
5324 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5325 data, data_len);
5326 cds_ssr_unprotect(__func__);
5327
5328 return ret;
5329}
5330
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305331static const struct
5332nla_policy
5333qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5334 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5335};
5336
5337/**
5338 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5339 * @wiphy: WIPHY structure pointer
5340 * @wdev: Wireless device structure pointer
5341 * @data: Pointer to the data received
5342 * @data_len: Length of the data received
5343 *
5344 * This function is used to get link properties like nss, rate flags and
5345 * operating frequency for the active connection with the given peer.
5346 *
5347 * Return: 0 on success and errno on failure
5348 */
5349static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5350 struct wireless_dev *wdev,
5351 const void *data,
5352 int data_len)
5353{
5354 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5355 struct net_device *dev = wdev->netdev;
5356 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5357 hdd_station_ctx_t *hdd_sta_ctx;
5358 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305359 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305360 uint32_t sta_id;
5361 struct sk_buff *reply_skb;
5362 uint32_t rate_flags = 0;
5363 uint8_t nss;
5364 uint8_t final_rate_flags = 0;
5365 uint32_t freq;
5366
Jeff Johnson1f61b612016-02-12 16:28:33 -08005367 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305368
Anurag Chouhan6d760662016-02-20 16:05:43 +05305369 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305370 hdd_err("Command not allowed in FTM mode");
5371 return -EPERM;
5372 }
5373
5374 if (0 != wlan_hdd_validate_context(hdd_ctx))
5375 return -EINVAL;
5376
5377 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5378 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005379 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305380 return -EINVAL;
5381 }
5382
5383 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005384 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305385 adapter->device_mode);
5386 return -EINVAL;
5387 }
5388
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305389 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305390 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005391 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305392 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5393
Krunal Sonib4326f22016-03-10 13:05:51 -08005394 if (adapter->device_mode == QDF_STA_MODE ||
5395 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305396 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5397 if ((hdd_sta_ctx->conn_info.connState !=
5398 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305399 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305400 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005401 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305402 MAC_ADDR_ARRAY(peer_mac));
5403 return -EINVAL;
5404 }
5405
5406 nss = hdd_sta_ctx->conn_info.nss;
5407 freq = cds_chan_to_freq(
5408 hdd_sta_ctx->conn_info.operationChannel);
5409 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005410 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5411 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305412
5413 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5414 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305415 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305416 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305417 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305418 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305419 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305420 break;
5421 }
5422
5423 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005424 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305425 MAC_ADDR_ARRAY(peer_mac));
5426 return -EINVAL;
5427 }
5428
5429 nss = adapter->aStaInfo[sta_id].nss;
5430 freq = cds_chan_to_freq(
5431 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5432 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5433 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005434 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305435 MAC_ADDR_ARRAY(peer_mac));
5436 return -EINVAL;
5437 }
5438
5439 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5440 if (rate_flags & eHAL_TX_RATE_VHT80) {
5441 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005442#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305443 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005444#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305445 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5446 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005447#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305448 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005449#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305450 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5451 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5452 } else if (rate_flags &
5453 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5454 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005455#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305456 if (rate_flags & eHAL_TX_RATE_HT40)
5457 final_rate_flags |=
5458 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005459#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305460 }
5461
5462 if (rate_flags & eHAL_TX_RATE_SGI) {
5463 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5464 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5465 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5466 }
5467 }
5468
5469 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5470 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5471
5472 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005473 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305474 return -EINVAL;
5475 }
5476
5477 if (nla_put_u8(reply_skb,
5478 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5479 nss) ||
5480 nla_put_u8(reply_skb,
5481 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5482 final_rate_flags) ||
5483 nla_put_u32(reply_skb,
5484 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5485 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005486 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305487 kfree_skb(reply_skb);
5488 return -EINVAL;
5489 }
5490
5491 return cfg80211_vendor_cmd_reply(reply_skb);
5492}
5493
5494/**
5495 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5496 * properties.
5497 * @wiphy: WIPHY structure pointer
5498 * @wdev: Wireless device structure pointer
5499 * @data: Pointer to the data received
5500 * @data_len: Length of the data received
5501 *
5502 * This function is used to get link properties like nss, rate flags and
5503 * operating frequency for the active connection with the given peer.
5504 *
5505 * Return: 0 on success and errno on failure
5506 */
5507static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5508 struct wireless_dev *wdev,
5509 const void *data,
5510 int data_len)
5511{
5512 int ret = 0;
5513
5514 cds_ssr_protect(__func__);
5515 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5516 wdev, data, data_len);
5517 cds_ssr_unprotect(__func__);
5518
5519 return ret;
5520}
5521
Peng Xu278d0122015-09-24 16:34:17 -07005522static const struct
5523nla_policy
5524qca_wlan_vendor_ota_test_policy
5525[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5526 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5527};
5528
5529/**
5530 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5531 * @wiphy: Pointer to wireless phy
5532 * @wdev: Pointer to wireless device
5533 * @data: Pointer to data
5534 * @data_len: Data length
5535 *
5536 * Return: 0 on success, negative errno on failure
5537 */
5538static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5539 struct wireless_dev *wdev,
5540 const void *data,
5541 int data_len)
5542{
5543 struct net_device *dev = wdev->netdev;
5544 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5545 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5546 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5547 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5548 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305549 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005550 uint32_t current_roam_state;
5551
Jeff Johnson1f61b612016-02-12 16:28:33 -08005552 ENTER_DEV(dev);
5553
Anurag Chouhan6d760662016-02-20 16:05:43 +05305554 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005555 hdd_err("Command not allowed in FTM mode");
5556 return -EPERM;
5557 }
5558
5559 if (0 != wlan_hdd_validate_context(hdd_ctx))
5560 return -EINVAL;
5561
5562 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5563 data, data_len,
5564 qca_wlan_vendor_ota_test_policy)) {
5565 hdd_err("invalid attr");
5566 return -EINVAL;
5567 }
5568
5569 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5570 hdd_err("attr ota test failed");
5571 return -EINVAL;
5572 }
5573
5574 ota_enable = nla_get_u8(
5575 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5576
5577 hdd_info(" OTA test enable = %d", ota_enable);
5578 if (ota_enable != 1) {
5579 hdd_err("Invalid value, only enable test mode is supported!");
5580 return -EINVAL;
5581 }
5582
5583 current_roam_state =
5584 sme_get_current_roam_state(hal, adapter->sessionId);
5585 status = sme_stop_roaming(hal, adapter->sessionId,
5586 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305587 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005588 hdd_err("Enable/Disable roaming failed");
5589 return -EINVAL;
5590 }
5591
5592 status = sme_ps_enable_disable(hal, adapter->sessionId,
5593 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305594 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005595 hdd_err("Enable/Disable power save failed");
5596 /* restore previous roaming setting */
5597 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5598 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5599 status = sme_start_roaming(hal, adapter->sessionId,
5600 eCsrHddIssued);
5601 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5602 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5603 status = sme_stop_roaming(hal, adapter->sessionId,
5604 eCsrHddIssued);
5605
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305606 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005607 hdd_err("Restoring roaming state failed");
5608
5609 return -EINVAL;
5610 }
5611
5612
5613 return 0;
5614}
5615
5616/**
5617 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5618 * @wiphy: Pointer to wireless phy
5619 * @wdev: Pointer to wireless device
5620 * @data: Pointer to data
5621 * @data_len: Data length
5622 *
5623 * Return: 0 on success, negative errno on failure
5624 */
5625static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5626 struct wireless_dev *wdev,
5627 const void *data,
5628 int data_len)
5629{
5630 int ret = 0;
5631
5632 cds_ssr_protect(__func__);
5633 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5634 cds_ssr_unprotect(__func__);
5635
5636 return ret;
5637}
5638
Peng Xu4d67c8f2015-10-16 16:02:26 -07005639/**
5640 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5641 * @wiphy: Pointer to wireless phy
5642 * @wdev: Pointer to wireless device
5643 * @data: Pointer to data
5644 * @data_len: Data length
5645 *
5646 * Return: 0 on success, negative errno on failure
5647 */
5648static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5649 struct wireless_dev *wdev,
5650 const void *data,
5651 int data_len)
5652{
5653 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5654 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005655 hdd_adapter_t *adapter;
5656 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005657 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5658 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005659 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005660
Jeff Johnson1f61b612016-02-12 16:28:33 -08005661 ENTER_DEV(dev);
5662
Peng Xu4d67c8f2015-10-16 16:02:26 -07005663 ret = wlan_hdd_validate_context(hdd_ctx);
5664 if (ret)
5665 return ret;
5666
5667 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5668
5669 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5670 data, data_len, NULL)) {
5671 hdd_err("Invalid ATTR");
5672 return -EINVAL;
5673 }
5674
5675 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5676 hdd_err("attr tx power scale failed");
5677 return -EINVAL;
5678 }
5679
5680 scale_value = nla_get_u8(tb
5681 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5682
5683 if (scale_value > MAX_TXPOWER_SCALE) {
5684 hdd_err("Invalid tx power scale level");
5685 return -EINVAL;
5686 }
5687
Peng Xu62c8c432016-05-09 15:23:02 -07005688 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005689
Peng Xu62c8c432016-05-09 15:23:02 -07005690 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005691 hdd_err("Set tx power scale failed");
5692 return -EINVAL;
5693 }
5694
5695 return 0;
5696}
5697
5698/**
5699 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5700 * @wiphy: Pointer to wireless phy
5701 * @wdev: Pointer to wireless device
5702 * @data: Pointer to data
5703 * @data_len: Data length
5704 *
5705 * Return: 0 on success, negative errno on failure
5706 */
5707static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5708 struct wireless_dev *wdev,
5709 const void *data,
5710 int data_len)
5711{
Peng Xu62c8c432016-05-09 15:23:02 -07005712 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005713
5714 cds_ssr_protect(__func__);
5715 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5716 data, data_len);
5717 cds_ssr_unprotect(__func__);
5718
5719 return ret;
5720}
5721
5722/**
5723 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5724 * @wiphy: Pointer to wireless phy
5725 * @wdev: Pointer to wireless device
5726 * @data: Pointer to data
5727 * @data_len: Data length
5728 *
5729 * Return: 0 on success, negative errno on failure
5730 */
5731static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5732 struct wireless_dev *wdev,
5733 const void *data,
5734 int data_len)
5735{
5736 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5737 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005738 hdd_adapter_t *adapter;
5739 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005740 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5741 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005742 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005743
Jeff Johnson1f61b612016-02-12 16:28:33 -08005744 ENTER_DEV(dev);
5745
Peng Xu4d67c8f2015-10-16 16:02:26 -07005746 ret = wlan_hdd_validate_context(hdd_ctx);
5747 if (ret)
5748 return ret;
5749
5750 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5751
5752 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5753 data, data_len, NULL)) {
5754 hdd_err("Invalid ATTR");
5755 return -EINVAL;
5756 }
5757
5758 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5759 hdd_err("attr tx power decrease db value failed");
5760 return -EINVAL;
5761 }
5762
5763 scale_value = nla_get_u8(tb
5764 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5765
Peng Xu62c8c432016-05-09 15:23:02 -07005766 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5767 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005768
Peng Xu62c8c432016-05-09 15:23:02 -07005769 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005770 hdd_err("Set tx power decrease db failed");
5771 return -EINVAL;
5772 }
5773
5774 return 0;
5775}
5776
5777/**
5778 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5779 * @wiphy: Pointer to wireless phy
5780 * @wdev: Pointer to wireless device
5781 * @data: Pointer to data
5782 * @data_len: Data length
5783 *
5784 * Return: 0 on success, negative errno on failure
5785 */
5786static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5787 struct wireless_dev *wdev,
5788 const void *data,
5789 int data_len)
5790{
Peng Xu62c8c432016-05-09 15:23:02 -07005791 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005792
5793 cds_ssr_protect(__func__);
5794 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5795 data, data_len);
5796 cds_ssr_unprotect(__func__);
5797
5798 return ret;
5799}
Peng Xu8fdaa492016-06-22 10:20:47 -07005800
5801/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305802 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5803 * @wiphy: Pointer to wireless phy
5804 * @wdev: Pointer to wireless device
5805 * @data: Pointer to data
5806 * @data_len: Data length
5807 *
5808 * Processes the conditional channel switch request and invokes the helper
5809 * APIs to process the channel switch request.
5810 *
5811 * Return: 0 on success, negative errno on failure
5812 */
5813static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5814 struct wireless_dev *wdev,
5815 const void *data,
5816 int data_len)
5817{
5818 int ret;
5819 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5820 struct net_device *dev = wdev->netdev;
5821 hdd_adapter_t *adapter;
5822 struct nlattr
5823 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5824 uint32_t freq_len, i;
5825 uint32_t *freq;
5826 uint8_t chans[QDF_MAX_NUM_CHAN];
5827
5828 ENTER_DEV(dev);
5829
5830 ret = wlan_hdd_validate_context(hdd_ctx);
5831 if (ret)
5832 return ret;
5833
5834 if (!hdd_ctx->config->enableDFSMasterCap) {
5835 hdd_err("DFS master capability is not present in the driver");
5836 return -EINVAL;
5837 }
5838
5839 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5840 hdd_err("Command not allowed in FTM mode");
5841 return -EPERM;
5842 }
5843
5844 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5845 if (adapter->device_mode != QDF_SAP_MODE) {
5846 hdd_err("Invalid device mode %d", adapter->device_mode);
5847 return -EINVAL;
5848 }
5849
5850 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5851 data, data_len, NULL)) {
5852 hdd_err("Invalid ATTR");
5853 return -EINVAL;
5854 }
5855
5856 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5857 hdd_err("Frequency list is missing");
5858 return -EINVAL;
5859 }
5860
5861 freq_len = nla_len(
5862 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5863 sizeof(uint32_t);
5864
5865 if (freq_len > QDF_MAX_NUM_CHAN) {
5866 hdd_err("insufficient space to hold channels");
5867 return -ENOMEM;
5868 }
5869
5870 hdd_debug("freq_len=%d", freq_len);
5871
5872 freq = nla_data(
5873 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5874
5875
5876 for (i = 0; i < freq_len; i++) {
5877 if (freq[i] == 0)
5878 chans[i] = 0;
5879 else
5880 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5881
5882 hdd_debug("freq[%d]=%d", i, freq[i]);
5883 }
5884
5885 /*
5886 * The input frequency list from user space is designed to be a
5887 * priority based frequency list. This is only to accommodate any
5888 * future request. But, current requirement is only to perform CAC
5889 * on a single channel. So, the first entry from the list is picked.
5890 *
5891 * If channel is zero, any channel in the available outdoor regulatory
5892 * domain will be selected.
5893 */
5894 ret = wlan_hdd_request_pre_cac(chans[0]);
5895 if (ret) {
5896 hdd_err("pre cac request failed with reason:%d", ret);
5897 return ret;
5898 }
5899
5900 return 0;
5901}
5902
5903/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005904 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5905 * @wiphy: Pointer to wireless phy
5906 * @wdev: Pointer to wireless device
5907 * @data: Pointer to data
5908 * @data_len: Data length
5909 *
5910 * This function is to process the p2p listen offload start vendor
5911 * command. It parses the input parameters and invoke WMA API to
5912 * send the command to firmware.
5913 *
5914 * Return: 0 on success, negative errno on failure
5915 */
5916static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5917 struct wireless_dev *wdev,
5918 const void *data,
5919 int data_len)
5920{
5921 int ret;
5922 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5923 struct net_device *dev = wdev->netdev;
5924 hdd_adapter_t *adapter;
5925 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5926 struct sir_p2p_lo_start params;
5927 QDF_STATUS status;
5928
5929 ENTER_DEV(dev);
5930
5931 ret = wlan_hdd_validate_context(hdd_ctx);
5932 if (ret)
5933 return ret;
5934
5935 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5936 hdd_err("Command not allowed in FTM mode");
5937 return -EPERM;
5938 }
5939
5940 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5941 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5942 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5943 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5944 hdd_err("Invalid device mode %d", adapter->device_mode);
5945 return -EINVAL;
5946 }
5947
5948 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5949 data, data_len, NULL)) {
5950 hdd_err("Invalid ATTR");
5951 return -EINVAL;
5952 }
5953
5954 memset(&params, 0, sizeof(params));
5955
5956 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5957 params.ctl_flags = 1; /* set to default value */
5958 else
5959 params.ctl_flags = nla_get_u32(tb
5960 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5961
5962 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5963 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5964 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
5965 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
5966 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
5967 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
5968 hdd_err("Attribute parsing failed");
5969 return -EINVAL;
5970 }
5971
5972 params.vdev_id = adapter->sessionId;
5973 params.freq = nla_get_u32(tb
5974 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
5975 if ((params.freq != 2412) && (params.freq != 2437) &&
5976 (params.freq != 2462)) {
5977 hdd_err("Invalid listening channel: %d", params.freq);
5978 return -EINVAL;
5979 }
5980
5981 params.period = nla_get_u32(tb
5982 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
5983 if (!((params.period > 0) && (params.period < UINT_MAX))) {
5984 hdd_err("Invalid period: %d", params.period);
5985 return -EINVAL;
5986 }
5987
5988 params.interval = nla_get_u32(tb
5989 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
5990 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
5991 hdd_err("Invalid interval: %d", params.interval);
5992 return -EINVAL;
5993 }
5994
5995 params.count = nla_get_u32(tb
5996 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
5997 if (!((params.count > 0) && (params.count < UINT_MAX))) {
5998 hdd_err("Invalid count: %d", params.count);
5999 return -EINVAL;
6000 }
6001
6002 params.device_types = nla_data(tb
6003 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6004 if (params.device_types == NULL) {
6005 hdd_err("Invalid device types");
6006 return -EINVAL;
6007 }
6008
6009 params.dev_types_len = nla_len(tb
6010 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6011 if (params.dev_types_len < 8) {
6012 hdd_err("Invalid device type length: %d", params.dev_types_len);
6013 return -EINVAL;
6014 }
6015
6016 params.probe_resp_tmplt = nla_data(tb
6017 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6018 if (params.probe_resp_tmplt == NULL) {
6019 hdd_err("Invalid probe response template");
6020 return -EINVAL;
6021 }
6022
6023 params.probe_resp_len = nla_len(tb
6024 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6025 if (params.probe_resp_len == 0) {
6026 hdd_err("Invalid probe resp template length: %d",
6027 params.probe_resp_len);
6028 return -EINVAL;
6029 }
6030
6031 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6032 params.freq, params.period, params.interval, params.count);
6033
6034 status = wma_p2p_lo_start(&params);
6035
6036 if (!QDF_IS_STATUS_SUCCESS(status)) {
6037 hdd_err("P2P LO start failed");
6038 return -EINVAL;
6039 }
6040
6041 return 0;
6042}
6043
6044
6045/**
6046 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6047 * @wiphy: Pointer to wireless phy
6048 * @wdev: Pointer to wireless device
6049 * @data: Pointer to data
6050 * @data_len: Data length
6051 *
6052 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6053 * to process p2p listen offload start vendor command.
6054 *
6055 * Return: 0 on success, negative errno on failure
6056 */
6057static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6058 struct wireless_dev *wdev,
6059 const void *data,
6060 int data_len)
6061{
6062 int ret = 0;
6063
6064 cds_ssr_protect(__func__);
6065 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6066 data, data_len);
6067 cds_ssr_unprotect(__func__);
6068
6069 return ret;
6070}
6071
6072/**
6073 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6074 * @wiphy: Pointer to wireless phy
6075 * @wdev: Pointer to wireless device
6076 * @data: Pointer to data
6077 * @data_len: Data length
6078 *
6079 * This function is to process the p2p listen offload stop vendor
6080 * command. It invokes WMA API to send command to firmware.
6081 *
6082 * Return: 0 on success, negative errno on failure
6083 */
6084static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6085 struct wireless_dev *wdev,
6086 const void *data,
6087 int data_len)
6088{
6089 QDF_STATUS status;
6090 hdd_adapter_t *adapter;
6091 struct net_device *dev = wdev->netdev;
6092
6093 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6094 hdd_err("Command not allowed in FTM mode");
6095 return -EPERM;
6096 }
6097
6098 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6099 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6100 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6101 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6102 hdd_err("Invalid device mode");
6103 return -EINVAL;
6104 }
6105
6106 status = wma_p2p_lo_stop(adapter->sessionId);
6107
6108 if (!QDF_IS_STATUS_SUCCESS(status)) {
6109 hdd_err("P2P LO stop failed");
6110 return -EINVAL;
6111 }
6112
6113 return 0;
6114}
6115
6116/**
6117 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6118 * @wiphy: Pointer to wireless phy
6119 * @wdev: Pointer to wireless device
6120 * @data: Pointer to data
6121 * @data_len: Data length
6122 *
6123 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6124 * to process p2p listen offload stop vendor command.
6125 *
6126 * Return: 0 on success, negative errno on failure
6127 */
6128static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6129 struct wireless_dev *wdev,
6130 const void *data,
6131 int data_len)
6132{
6133 int ret = 0;
6134
6135 cds_ssr_protect(__func__);
6136 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6137 data, data_len);
6138 cds_ssr_unprotect(__func__);
6139
6140 return ret;
6141}
6142
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306143/**
6144 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6145 * @wiphy: Pointer to wireless phy
6146 * @wdev: Pointer to wireless device
6147 * @data: Pointer to data
6148 * @data_len: Data length
6149 *
6150 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6151 * to process the conditional channel switch request.
6152 *
6153 * Return: 0 on success, negative errno on failure
6154 */
6155static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6156 struct wireless_dev *wdev,
6157 const void *data,
6158 int data_len)
6159{
6160 int ret;
6161
6162 cds_ssr_protect(__func__);
6163 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6164 data, data_len);
6165 cds_ssr_unprotect(__func__);
6166
6167 return ret;
6168}
6169
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306170/*
6171 * define short names for the global vendor params
6172 * used by __wlan_hdd_cfg80211_bpf_offload()
6173 */
6174#define BPF_INVALID \
6175 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6176#define BPF_SET_RESET \
6177 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6178#define BPF_VERSION \
6179 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6180#define BPF_FILTER_ID \
6181 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6182#define BPF_PACKET_SIZE \
6183 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6184#define BPF_CURRENT_OFFSET \
6185 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6186#define BPF_PROGRAM \
6187 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6188#define BPF_MAX \
6189 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006190
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306191static const struct nla_policy
6192wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6193 [BPF_SET_RESET] = {.type = NLA_U32},
6194 [BPF_VERSION] = {.type = NLA_U32},
6195 [BPF_FILTER_ID] = {.type = NLA_U32},
6196 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6197 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6198 [BPF_PROGRAM] = {.type = NLA_U8},
6199};
6200
6201/**
6202 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6203 * @hdd_context: hdd_context
6204 * @bpf_get_offload: struct for get offload
6205 *
6206 * This function receives the response/data from the lower layer and
6207 * checks to see if the thread is still waiting then post the results to
6208 * upper layer, if the request has timed out then ignore.
6209 *
6210 * Return: None
6211 */
6212void hdd_get_bpf_offload_cb(void *hdd_context,
6213 struct sir_bpf_get_offload *data)
6214{
6215 hdd_context_t *hdd_ctx = hdd_context;
6216 struct hdd_bpf_context *context;
6217
6218 ENTER();
6219
6220 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006221 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306222 data);
6223 return;
6224 }
6225
6226 spin_lock(&hdd_context_lock);
6227
6228 context = &bpf_context;
6229 /* The caller presumably timed out so there is nothing we can do */
6230 if (context->magic != BPF_CONTEXT_MAGIC) {
6231 spin_unlock(&hdd_context_lock);
6232 return;
6233 }
6234
6235 /* context is valid so caller is still waiting */
6236 /* paranoia: invalidate the magic */
6237 context->magic = 0;
6238
6239 context->capability_response = *data;
6240 complete(&context->completion);
6241
6242 spin_unlock(&hdd_context_lock);
6243
6244 return;
6245}
6246
6247/**
6248 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6249 * @hdd_context: hdd_context
6250 * @bpf_get_offload: struct for get offload
6251 *
6252 * Return: 0 on success, error number otherwise.
6253 */
6254static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6255 struct sir_bpf_get_offload *bpf_get_offload)
6256{
6257 struct sk_buff *skb;
6258 uint32_t nl_buf_len;
6259
6260 ENTER();
6261
6262 nl_buf_len = NLMSG_HDRLEN;
6263 nl_buf_len +=
6264 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6265 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6266
6267 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6268 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006269 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306270 return -ENOMEM;
6271 }
6272
Jeff Johnson77848112016-06-29 14:52:06 -07006273 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306274 bpf_get_offload->bpf_version,
6275 bpf_get_offload->max_bytes_for_bpf_inst);
6276
6277 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6278 bpf_get_offload->max_bytes_for_bpf_inst) ||
6279 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006280 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306281 goto nla_put_failure;
6282 }
6283
6284 cfg80211_vendor_cmd_reply(skb);
6285 EXIT();
6286 return 0;
6287
6288nla_put_failure:
6289 kfree_skb(skb);
6290 return -EINVAL;
6291}
6292
6293/**
6294 * hdd_get_bpf_offload - Get BPF offload Capabilities
6295 * @hdd_ctx: Hdd context
6296 *
6297 * Return: 0 on success, errno on failure
6298 */
6299static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6300{
6301 unsigned long rc;
6302 struct hdd_bpf_context *context;
6303 QDF_STATUS status;
6304 int ret;
6305
6306 ENTER();
6307
6308 spin_lock(&hdd_context_lock);
6309 context = &bpf_context;
6310 context->magic = BPF_CONTEXT_MAGIC;
6311 INIT_COMPLETION(context->completion);
6312 spin_unlock(&hdd_context_lock);
6313
6314 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6315 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006316 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306317 return -EINVAL;
6318 }
6319 /* request was sent -- wait for the response */
6320 rc = wait_for_completion_timeout(&context->completion,
6321 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6322 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006323 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306324 spin_lock(&hdd_context_lock);
6325 context->magic = 0;
6326 spin_unlock(&hdd_context_lock);
6327
6328 return -ETIMEDOUT;
6329 }
6330 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6331 &bpf_context.capability_response);
6332 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006333 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306334
6335 EXIT();
6336 return ret;
6337}
6338
6339/**
6340 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6341 * @hdd_ctx: Hdd context
6342 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306343 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306344 *
6345 * Return: 0 on success; errno on failure
6346 */
6347static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6348 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306349 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306350{
6351 struct sir_bpf_set_offload *bpf_set_offload;
6352 QDF_STATUS status;
6353 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306354 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306355
6356 ENTER();
6357
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306358 if (adapter->device_mode == QDF_STA_MODE ||
6359 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6360 if (!hdd_conn_is_connected(
6361 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6362 hdd_err("Not in Connected state!");
6363 return -ENOTSUPP;
6364 }
6365 }
6366
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306367 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6368 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006369 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306370 return -ENOMEM;
6371 }
6372 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6373
6374 /* Parse and fetch bpf packet size */
6375 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006376 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306377 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306378 goto fail;
6379 }
6380 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6381
6382 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006383 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306384 goto post_sme;
6385 }
6386
6387 /* Parse and fetch bpf program */
6388 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006389 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306390 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306391 goto fail;
6392 }
6393
6394 prog_len = nla_len(tb[BPF_PROGRAM]);
6395 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306396
6397 if (bpf_set_offload->program == NULL) {
6398 hdd_err("qdf_mem_malloc failed for bpf offload program");
6399 ret = -ENOMEM;
6400 goto fail;
6401 }
6402
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306403 bpf_set_offload->current_length = prog_len;
6404 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306405 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306406
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306407 hdd_info("BPF set instructions");
6408 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6409 bpf_set_offload->program, prog_len);
6410
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306411 /* Parse and fetch filter Id */
6412 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006413 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306414 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306415 goto fail;
6416 }
6417 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6418
6419 /* Parse and fetch current offset */
6420 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006421 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306422 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306423 goto fail;
6424 }
6425 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6426
6427post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006428 hdd_notice("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306429 bpf_set_offload->session_id,
6430 bpf_set_offload->version,
6431 bpf_set_offload->filter_id,
6432 bpf_set_offload->total_length,
6433 bpf_set_offload->current_length,
6434 bpf_set_offload->current_offset);
6435
6436 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6437 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006438 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306439 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306440 goto fail;
6441 }
6442 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306443
6444fail:
6445 if (bpf_set_offload->current_length)
6446 qdf_mem_free(bpf_set_offload->program);
6447 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306448 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306449}
6450
6451/**
6452 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6453 * @wiphy: wiphy structure pointer
6454 * @wdev: Wireless device structure pointer
6455 * @data: Pointer to the data received
6456 * @data_len: Length of @data
6457 *
6458 * Return: 0 on success; errno on failure
6459 */
6460static int
6461__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6462 struct wireless_dev *wdev,
6463 const void *data, int data_len)
6464{
6465 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6466 struct net_device *dev = wdev->netdev;
6467 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6468 struct nlattr *tb[BPF_MAX + 1];
6469 int ret_val, packet_filter_subcmd;
6470
6471 ENTER();
6472
6473 ret_val = wlan_hdd_validate_context(hdd_ctx);
6474 if (ret_val)
6475 return ret_val;
6476
6477 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006478 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306479 return -EINVAL;
6480 }
6481
6482 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006483 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306484 return -ENOTSUPP;
6485 }
6486
6487 if (nla_parse(tb, BPF_MAX, data, data_len,
6488 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006489 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306490 return -EINVAL;
6491 }
6492
6493 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006494 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306495 return -EINVAL;
6496 }
6497
6498 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6499
6500 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6501 return hdd_get_bpf_offload(hdd_ctx);
6502 else
6503 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306504 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306505}
6506
6507/**
6508 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6509 * @wiphy: wiphy structure pointer
6510 * @wdev: Wireless device structure pointer
6511 * @data: Pointer to the data received
6512 * @data_len: Length of @data
6513 *
6514 * Return: 0 on success; errno on failure
6515 */
6516
6517static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6518 struct wireless_dev *wdev,
6519 const void *data, int data_len)
6520{
6521 int ret;
6522
6523 cds_ssr_protect(__func__);
6524 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6525 cds_ssr_unprotect(__func__);
6526
6527 return ret;
6528}
6529
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306530/**
6531 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6532 * @pre_cac_adapter: AP adapter used for pre cac
6533 * @status: Status (true or false)
6534 * @handle: Global handle
6535 *
6536 * Sets the status of pre cac i.e., whether the pre cac is active or not
6537 *
6538 * Return: Zero on success, non-zero on failure
6539 */
6540static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6541 bool status, tHalHandle handle)
6542{
6543 QDF_STATUS ret;
6544
6545 ret = wlan_sap_set_pre_cac_status(
6546 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6547 if (QDF_IS_STATUS_ERROR(ret))
6548 return -EINVAL;
6549
6550 return 0;
6551}
6552
6553/**
6554 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6555 * @ap_adapter: AP adapter
6556 * @chan_before_pre_cac: Channel
6557 *
6558 * Saves the channel which the AP was beaconing on before moving to the pre
6559 * cac channel. If radar is detected on the pre cac channel, this saved
6560 * channel will be used for AP operations.
6561 *
6562 * Return: Zero on success, non-zero on failure
6563 */
6564static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6565 uint8_t chan_before_pre_cac)
6566{
6567 QDF_STATUS ret;
6568
6569 ret = wlan_sap_set_chan_before_pre_cac(
6570 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6571 if (QDF_IS_STATUS_ERROR(ret))
6572 return -EINVAL;
6573
6574 return 0;
6575}
6576
6577/**
6578 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6579 * @ap_adapter: AP adapter
6580 * @nol: Non-occupancy list
6581 * @nol_len: Length of NOL
6582 *
6583 * Get the NOL for SAP
6584 *
6585 * Return: Zero on success, non-zero on failure
6586 */
6587static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6588 uint32_t *nol_len)
6589{
6590 QDF_STATUS ret;
6591
6592 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6593 nol, nol_len);
6594 if (QDF_IS_STATUS_ERROR(ret))
6595 return -EINVAL;
6596
6597 return 0;
6598}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306599
6600/**
6601 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6602 * @hdd_ctx: HDD context
6603 * @ap_adapter: AP adapter
6604 * @channel: Channel requested by userspace
6605 * @pre_cac_chan: Pointer to the pre CAC channel
6606 *
6607 * Validates the channel provided by userspace. If user provided channel 0,
6608 * a valid outdoor channel must be selected from the regulatory channel.
6609 *
6610 * Return: Zero on success and non zero value on error
6611 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006612static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6613 hdd_adapter_t *ap_adapter,
6614 uint8_t channel,
6615 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306616{
6617 uint32_t i, j;
6618 QDF_STATUS status;
6619 int ret;
6620 uint8_t nol[QDF_MAX_NUM_CHAN];
6621 uint32_t nol_len = 0, weight_len = 0;
6622 bool found;
6623 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6624 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6625 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6626
6627 if (0 == channel) {
6628 /* Channel is not obtained from PCL because PCL may not have
6629 * the entire channel list. For example: if SAP is up on
6630 * channel 6 and PCL is queried for the next SAP interface,
6631 * if SCC is preferred, the PCL will contain only the channel
6632 * 6. But, we are in need of a DFS channel. So, going with the
6633 * first channel from the valid channel list.
6634 */
6635 status = cds_get_valid_chans(channel_list, &len);
6636 if (QDF_IS_STATUS_ERROR(status)) {
6637 hdd_err("Failed to get channel list");
6638 return -EINVAL;
6639 }
6640 cds_update_with_safe_channel_list(channel_list, &len,
6641 pcl_weights, weight_len);
6642 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6643 for (i = 0; i < len; i++) {
6644 found = false;
6645 for (j = 0; j < nol_len; j++) {
6646 if (channel_list[i] == nol[j]) {
6647 found = true;
6648 break;
6649 }
6650 }
6651 if (found)
6652 continue;
6653 if (CDS_IS_DFS_CH(channel_list[i])) {
6654 *pre_cac_chan = channel_list[i];
6655 break;
6656 }
6657 }
6658 if (*pre_cac_chan == 0) {
6659 hdd_err("unable to find outdoor channel");
6660 return -EINVAL;
6661 }
6662 } else {
6663 /* Only when driver selects a channel, check is done for
6664 * unnsafe and NOL channels. When user provides a fixed channel
6665 * the user is expected to take care of this.
6666 */
6667 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6668 !CDS_IS_DFS_CH(channel)) {
6669 hdd_err("Invalid channel for pre cac:%d", channel);
6670 return -EINVAL;
6671 } else {
6672 *pre_cac_chan = channel;
6673 }
6674 }
6675 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6676 return 0;
6677}
6678
6679/**
6680 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6681 * @channel: Channel option provided by userspace
6682 *
6683 * Sets the driver to the required hardware mode and start an adapater for
6684 * pre CAC which will mimic an AP.
6685 *
6686 * Return: Zero on success, non-zero value on error
6687 */
6688int wlan_hdd_request_pre_cac(uint8_t channel)
6689{
6690 uint8_t pre_cac_chan = 0;
6691 hdd_context_t *hdd_ctx;
6692 int ret;
6693 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6694 hdd_ap_ctx_t *hdd_ap_ctx;
6695 QDF_STATUS status;
6696 struct wiphy *wiphy;
6697 struct net_device *dev;
6698 struct cfg80211_chan_def chandef;
6699 enum nl80211_channel_type channel_type;
6700 uint32_t freq;
6701 struct ieee80211_channel *chan;
6702 tHalHandle handle;
6703 bool val;
6704
6705 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6706 if (0 != wlan_hdd_validate_context(hdd_ctx))
6707 return -EINVAL;
6708
6709 if (cds_get_connection_count() > 1) {
6710 hdd_err("pre cac not allowed in concurrency");
6711 return -EINVAL;
6712 }
6713
6714 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6715 if (!ap_adapter) {
6716 hdd_err("unable to get SAP adapter");
6717 return -EINVAL;
6718 }
6719
6720 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6721 if (!handle) {
6722 hdd_err("Invalid handle");
6723 return -EINVAL;
6724 }
6725
6726 val = wlan_sap_is_pre_cac_active(handle);
6727 if (val) {
6728 hdd_err("pre cac is already in progress");
6729 return -EINVAL;
6730 }
6731
6732 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6733 if (!hdd_ap_ctx) {
6734 hdd_err("SAP context is NULL");
6735 return -EINVAL;
6736 }
6737
6738 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6739 hdd_err("SAP is already on DFS channel:%d",
6740 hdd_ap_ctx->operatingChannel);
6741 return -EINVAL;
6742 }
6743
6744 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6745 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6746 hdd_ap_ctx->operatingChannel);
6747 return -EINVAL;
6748 }
6749
6750 hdd_info("channel:%d", channel);
6751
6752 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6753 &pre_cac_chan);
6754 if (ret != 0)
6755 return ret;
6756
6757 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6758 * connection update should result in DBS mode
6759 */
6760 status = cds_update_and_wait_for_connection_update(
6761 ap_adapter->sessionId,
6762 pre_cac_chan,
6763 SIR_UPDATE_REASON_PRE_CAC);
6764 if (QDF_IS_STATUS_ERROR(status)) {
6765 hdd_err("error in moving to DBS mode");
6766 return -EINVAL;
6767 }
6768
6769 hdd_debug("starting pre cac SAP adapter");
6770
6771 /* Starting a SAP adapter:
6772 * Instead of opening an adapter, we could just do a SME open session
6773 * for AP type. But, start BSS would still need an adapter.
6774 * So, this option is not taken.
6775 *
6776 * hdd open adapter is going to register this precac interface with
6777 * user space. This interface though exposed to user space will be in
6778 * DOWN state. Consideration was done to avoid this registration to the
6779 * user space. But, as part of SAP operations multiple events are sent
6780 * to user space. Some of these events received from unregistered
6781 * interface was causing crashes. So, retaining the registration.
6782 *
6783 * So, this interface would remain registered and will remain in DOWN
6784 * state for the CAC duration. We will add notes in the feature
6785 * announcement to not use this temporary interface for any activity
6786 * from user space.
6787 */
6788 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6789 wlan_hdd_get_intf_addr(hdd_ctx),
6790 NET_NAME_UNKNOWN, true);
6791 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306792 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306793 return -EINVAL;
6794 }
6795
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306796 /*
6797 * This interface is internally created by the driver. So, no interface
6798 * up comes for this interface from user space and hence starting
6799 * the adapter internally.
6800 */
6801 if (hdd_start_adapter(pre_cac_adapter)) {
6802 hdd_err("error starting the pre cac adapter");
6803 goto close_pre_cac_adapter;
6804 }
6805
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306806 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6807
6808 wiphy = hdd_ctx->wiphy;
6809 dev = pre_cac_adapter->dev;
6810
6811 /* Since this is only a dummy interface lets us use the IEs from the
6812 * other active SAP interface. In regular scenarios, these IEs would
6813 * come from the user space entity
6814 */
6815 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6816 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6817 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6818 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306819 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306820 }
6821 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6822 ap_adapter->sessionCtx.ap.beacon,
6823 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6824 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6825 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6826 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6827 ap_adapter->sessionCtx.ap.sapConfig.authType;
6828
6829 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6830 * to operate on the same bandwidth as that of the 2.4GHz operations.
6831 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6832 */
6833 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6834 case CH_WIDTH_20MHZ:
6835 channel_type = NL80211_CHAN_HT20;
6836 break;
6837 case CH_WIDTH_40MHZ:
6838 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6839 ap_adapter->sessionCtx.ap.sapConfig.channel)
6840 channel_type = NL80211_CHAN_HT40PLUS;
6841 else
6842 channel_type = NL80211_CHAN_HT40MINUS;
6843 break;
6844 default:
6845 channel_type = NL80211_CHAN_NO_HT;
6846 break;
6847 }
6848
6849 freq = cds_chan_to_freq(pre_cac_chan);
6850 chan = __ieee80211_get_channel(wiphy, freq);
6851 if (!chan) {
6852 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306853 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306854 }
6855
6856 cfg80211_chandef_create(&chandef, chan, channel_type);
6857
6858 hdd_debug("orig width:%d channel_type:%d freq:%d",
6859 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6860 channel_type, freq);
6861
6862 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6863 if (0 != ret) {
6864 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306865 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306866 }
6867
6868 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6869 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6870 eHIDDEN_SSID_NOT_IN_USE, false);
6871 if (QDF_IS_STATUS_ERROR(status)) {
6872 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306873 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306874 }
6875
6876 /*
6877 * The pre cac status is set here. But, it would not be reset explicitly
6878 * anywhere, since after the pre cac success/failure, the pre cac
6879 * adapter itself would be removed.
6880 */
6881 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6882 if (0 != ret) {
6883 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306884 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306885 }
6886
6887 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6888 hdd_ap_ctx->operatingChannel);
6889 if (0 != ret) {
6890 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306891 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306892 }
6893
6894 ap_adapter->pre_cac_chan = pre_cac_chan;
6895
6896 return 0;
6897
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306898stop_close_pre_cac_adapter:
6899 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306900 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6901 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306902close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306903 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6904 return -EINVAL;
6905}
6906
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306907/**
6908 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6909 *
6910 * Return: None
6911 */
6912void hdd_init_bpf_completion(void)
6913{
6914 init_completion(&bpf_context.completion);
6915}
6916
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306917static const struct nla_policy
6918wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6919 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6920};
6921
Agrawal Ashish65634612016-08-18 13:24:32 +05306922static const struct nla_policy
6923wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
6924 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
6925 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
6926};
6927
6928/**
6929 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
6930 * @wiphy: Pointer to wireless phy
6931 * @wdev: Pointer to wireless device
6932 * @data: Pointer to data
6933 * @data_len: Length of @data
6934 *
6935 * This function parses the incoming NL vendor command data attributes and
6936 * updates the SAP context about channel_hint and DFS mode.
6937 * If channel_hint is set, SAP will choose that channel
6938 * as operating channel.
6939 *
6940 * If DFS mode is enabled, driver will include DFS channels
6941 * in ACS else driver will skip DFS channels.
6942 *
6943 * Return: 0 on success, negative errno on failure
6944 */
6945static int
6946__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6947 struct wireless_dev *wdev,
6948 const void *data, int data_len)
6949{
6950 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6951 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
6952 int ret;
6953 struct acs_dfs_policy *acs_policy;
6954 int mode = DFS_MODE_NONE;
6955 int channel_hint = 0;
6956
6957 ENTER_DEV(wdev->netdev);
6958
6959 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6960 hdd_err("Command not allowed in FTM mode");
6961 return -EINVAL;
6962 }
6963
6964 ret = wlan_hdd_validate_context(hdd_ctx);
6965 if (0 != ret)
6966 return ret;
6967
6968 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
6969 data, data_len,
6970 wlan_hdd_set_acs_dfs_config_policy)) {
6971 hdd_err("invalid attr");
6972 return -EINVAL;
6973 }
6974
6975 acs_policy = &hdd_ctx->acs_policy;
6976 /*
6977 * SCM sends this attribute to restrict SAP from choosing
6978 * DFS channels from ACS.
6979 */
6980 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
6981 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
6982
6983 if (!IS_DFS_MODE_VALID(mode)) {
6984 hdd_err("attr acs dfs mode is not valid");
6985 return -EINVAL;
6986 }
6987 acs_policy->acs_dfs_mode = mode;
6988
6989 /*
6990 * SCM sends this attribute to provide an active channel,
6991 * to skip redundant ACS between drivers, and save driver start up time
6992 */
6993 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
6994 channel_hint = nla_get_u8(
6995 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
6996
6997 if (!IS_CHANNEL_VALID(channel_hint)) {
6998 hdd_err("acs channel is not valid");
6999 return -EINVAL;
7000 }
7001 acs_policy->acs_channel = channel_hint;
7002
7003 return 0;
7004}
7005
7006/**
7007 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7008 * @wiphy: wiphy structure pointer
7009 * @wdev: Wireless device structure pointer
7010 * @data: Pointer to the data received
7011 * @data_len: Length of @data
7012 *
7013 * This function parses the incoming NL vendor command data attributes and
7014 * updates the SAP context about channel_hint and DFS mode.
7015 *
7016 * Return: 0 on success; errno on failure
7017 */
7018static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7019 struct wireless_dev *wdev,
7020 const void *data, int data_len)
7021{
7022 int ret;
7023
7024 cds_ssr_protect(__func__);
7025 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7026 cds_ssr_unprotect(__func__);
7027
7028 return ret;
7029}
7030
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307031/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307032 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7033 * @mode : cfg80211 dfs mode
7034 *
7035 * Return: return csr sta roam dfs mode else return NONE
7036 */
7037static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7038 enum dfs_mode mode)
7039{
7040 switch (mode) {
7041 case DFS_MODE_ENABLE:
7042 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7043 break;
7044 case DFS_MODE_DISABLE:
7045 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7046 break;
7047 case DFS_MODE_DEPRIORITIZE:
7048 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7049 break;
7050 default:
7051 hdd_err("STA Roam policy dfs mode is NONE");
7052 return CSR_STA_ROAM_POLICY_NONE;
7053 }
7054}
7055
7056static const struct nla_policy
7057wlan_hdd_set_sta_roam_config_policy[
7058QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7059 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7060 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7061};
7062
7063/**
7064 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7065 * for station connection or roaming.
7066 * @wiphy: Pointer to wireless phy
7067 * @wdev: Pointer to wireless device
7068 * @data: Pointer to data
7069 * @data_len: Length of @data
7070 *
7071 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7072 * channels needs to be skipped in scanning or not.
7073 * If dfs_mode is disabled, driver will not scan DFS channels.
7074 * If skip_unsafe_channels is set, driver will skip unsafe channels
7075 * in Scanning.
7076 *
7077 * Return: 0 on success, negative errno on failure
7078 */
7079static int
7080__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7081 struct wireless_dev *wdev,
7082 const void *data, int data_len)
7083{
7084 struct net_device *dev = wdev->netdev;
7085 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7086 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7087 struct nlattr *tb[
7088 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7089 int ret;
7090 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7091 enum dfs_mode mode = DFS_MODE_NONE;
7092 bool skip_unsafe_channels = false;
7093 QDF_STATUS status;
7094
7095 ENTER_DEV(dev);
7096
7097 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7098 hdd_err("Command not allowed in FTM mode");
7099 return -EINVAL;
7100 }
7101
7102 ret = wlan_hdd_validate_context(hdd_ctx);
7103 if (0 != ret)
7104 return ret;
7105 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7106 data, data_len,
7107 wlan_hdd_set_sta_roam_config_policy)) {
7108 hdd_err("invalid attr");
7109 return -EINVAL;
7110 }
7111 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7112 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7113 if (!IS_DFS_MODE_VALID(mode)) {
7114 hdd_err("attr sta roam dfs mode policy is not valid");
7115 return -EINVAL;
7116 }
7117
7118 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7119
7120 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7121 skip_unsafe_channels = nla_get_u8(
7122 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7123
7124 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7125 skip_unsafe_channels, adapter->sessionId);
7126
7127 if (!QDF_IS_STATUS_SUCCESS(status)) {
7128 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7129 return -EINVAL;
7130 }
7131 return 0;
7132}
7133
7134/**
7135 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7136 * connection and roaming for station.
7137 * @wiphy: wiphy structure pointer
7138 * @wdev: Wireless device structure pointer
7139 * @data: Pointer to the data received
7140 * @data_len: Length of @data
7141 *
7142 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7143 * channels needs to be skipped in scanning or not.
7144 * If dfs_mode is disabled, driver will not scan DFS channels.
7145 * If skip_unsafe_channels is set, driver will skip unsafe channels
7146 * in Scanning.
7147 * Return: 0 on success; errno on failure
7148 */
7149static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7150 struct wireless_dev *wdev,
7151 const void *data, int data_len)
7152{
7153 int ret;
7154
7155 cds_ssr_protect(__func__);
7156 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7157 cds_ssr_unprotect(__func__);
7158
7159 return ret;
7160}
7161
Agrawal Ashish467dde42016-09-08 18:44:22 +05307162#ifdef FEATURE_WLAN_CH_AVOID
7163/**
7164 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7165 * is on unsafe channel.
7166 * @wiphy: wiphy structure pointer
7167 * @wdev: Wireless device structure pointer
7168 * @data: Pointer to the data received
7169 * @data_len: Length of @data
7170 *
7171 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7172 * on any of unsafe channels.
7173 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7174 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7175 *
7176 * Return: 0 on success; errno on failure
7177 */
7178static int
7179__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7180 struct wireless_dev *wdev,
7181 const void *data, int data_len)
7182{
7183 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7184 int ret;
7185 uint16_t unsafe_channel_count;
7186 int unsafe_channel_index;
7187 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7188
7189 ENTER_DEV(wdev->netdev);
7190
7191 if (!qdf_ctx) {
7192 cds_err("qdf_ctx is NULL");
7193 return -EINVAL;
7194 }
7195
7196 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7197 hdd_err("Command not allowed in FTM mode");
7198 return -EINVAL;
7199 }
7200
7201 ret = wlan_hdd_validate_context(hdd_ctx);
7202 if (0 != ret)
7203 return ret;
7204 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7205 &(hdd_ctx->unsafe_channel_count),
7206 sizeof(hdd_ctx->unsafe_channel_list));
7207
7208 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7209 (uint16_t)NUM_CHANNELS);
7210 for (unsafe_channel_index = 0;
7211 unsafe_channel_index < unsafe_channel_count;
7212 unsafe_channel_index++) {
7213 hdd_info("Channel %d is not safe",
7214 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7215 }
7216 hdd_unsafe_channel_restart_sap(hdd_ctx);
7217 return 0;
7218}
7219
7220/**
7221 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7222 * is on unsafe channel.
7223 * @wiphy: wiphy structure pointer
7224 * @wdev: Wireless device structure pointer
7225 * @data: Pointer to the data received
7226 * @data_len: Length of @data
7227 *
7228 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7229 * on any of unsafe channels.
7230 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7231 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7232 *
7233 * Return: 0 on success; errno on failure
7234 */
7235static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7236 struct wireless_dev *wdev,
7237 const void *data, int data_len)
7238{
7239 int ret;
7240
7241 cds_ssr_protect(__func__);
7242 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7243 cds_ssr_unprotect(__func__);
7244
7245 return ret;
7246}
7247
7248#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307249/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307250 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7251 * SAP is on unsafe channel.
7252 * @wiphy: wiphy structure pointer
7253 * @wdev: Wireless device structure pointer
7254 * @data: Pointer to the data received
7255 * @data_len: Length of @data
7256 *
7257 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7258 * driver.
7259 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7260 * will initiate restart of sap.
7261 *
7262 * Return: 0 on success; errno on failure
7263 */
7264static int
7265__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7266 struct wireless_dev *wdev,
7267 const void *data, int data_len)
7268{
7269 struct net_device *ndev = wdev->netdev;
7270 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7271 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7272 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7273 uint8_t config_channel = 0;
7274 hdd_ap_ctx_t *ap_ctx;
7275 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307276 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307277
7278 ENTER();
7279
7280 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007281 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307282 return -EINVAL;
7283 }
7284
7285 ret = wlan_hdd_validate_context(hdd_ctx);
7286 if (0 != ret)
7287 return -EINVAL;
7288
7289 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7290 data, data_len,
7291 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007292 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307293 return -EINVAL;
7294 }
7295
7296 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7297 if (!test_bit(SOFTAP_BSS_STARTED,
7298 &hostapd_adapter->event_flags)) {
7299 hdd_err("SAP is not started yet. Restart sap will be invalid");
7300 return -EINVAL;
7301 }
7302
7303 config_channel =
7304 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7305
7306 if (!((IS_24G_CH(config_channel)) ||
7307 (IS_5G_CH(config_channel)))) {
7308 hdd_err("Channel %d is not valid to restart SAP",
7309 config_channel);
7310 return -ENOTSUPP;
7311 }
7312
7313 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7314 ap_ctx->sapConfig.channel = config_channel;
7315 ap_ctx->sapConfig.ch_params.ch_width =
7316 ap_ctx->sapConfig.ch_width_orig;
7317
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007318 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307319 ap_ctx->sapConfig.sec_ch,
7320 &ap_ctx->sapConfig.ch_params);
7321
7322 cds_restart_sap(hostapd_adapter);
7323 }
7324
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307325 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7326 uint32_t freq_len, i;
7327 uint32_t *freq;
7328 uint8_t chans[QDF_MAX_NUM_CHAN];
7329
7330 hdd_debug("setting mandatory freq/chan list");
7331
7332 freq_len = nla_len(
7333 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7334 sizeof(uint32_t);
7335
7336 if (freq_len > QDF_MAX_NUM_CHAN) {
7337 hdd_err("insufficient space to hold channels");
7338 return -ENOMEM;
7339 }
7340
7341 freq = nla_data(
7342 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7343
7344 hdd_debug("freq_len=%d", freq_len);
7345
7346 for (i = 0; i < freq_len; i++) {
7347 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7348 hdd_debug("freq[%d]=%d", i, freq[i]);
7349 }
7350
7351 status = cds_set_sap_mandatory_channels(chans, freq_len);
7352 if (QDF_IS_STATUS_ERROR(status))
7353 return -EINVAL;
7354 }
7355
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307356 return 0;
7357}
7358
7359/**
7360 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7361 * @wiphy: wiphy structure pointer
7362 * @wdev: Wireless device structure pointer
7363 * @data: Pointer to the data received
7364 * @data_len: Length of @data
7365 *
7366 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7367 * driver.
7368 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7369 * will initiate restart of sap.
7370 *
7371 * Return: 0 on success; errno on failure
7372 */
7373static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7374 struct wireless_dev *wdev,
7375 const void *data, int data_len)
7376{
7377 int ret;
7378
7379 cds_ssr_protect(__func__);
7380 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7381 wdev, data, data_len);
7382 cds_ssr_unprotect(__func__);
7383
7384 return ret;
7385}
7386
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307387#undef BPF_INVALID
7388#undef BPF_SET_RESET
7389#undef BPF_VERSION
7390#undef BPF_ID
7391#undef BPF_PACKET_SIZE
7392#undef BPF_CURRENT_OFFSET
7393#undef BPF_PROGRAM
7394#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307395
7396/**
7397 * define short names for the global vendor params
7398 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7399 */
7400#define PARAM_TOTAL_CMD_EVENT_WAKE \
7401 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7402#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7403 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7404#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7405 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7406#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7407 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7408#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7409 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7410#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7411 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7412#define PARAM_TOTAL_RX_DATA_WAKE \
7413 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7414#define PARAM_RX_UNICAST_CNT \
7415 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7416#define PARAM_RX_MULTICAST_CNT \
7417 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7418#define PARAM_RX_BROADCAST_CNT \
7419 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7420#define PARAM_ICMP_PKT \
7421 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7422#define PARAM_ICMP6_PKT \
7423 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7424#define PARAM_ICMP6_RA \
7425 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7426#define PARAM_ICMP6_NA \
7427 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7428#define PARAM_ICMP6_NS \
7429 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7430#define PARAM_ICMP4_RX_MULTICAST_CNT \
7431 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7432#define PARAM_ICMP6_RX_MULTICAST_CNT \
7433 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7434#define PARAM_OTHER_RX_MULTICAST_CNT \
7435 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7436
7437
7438/**
7439 * hdd_send_wakelock_stats() - API to send wakelock stats
7440 * @ctx: context to be passed to callback
7441 * @data: data passed to callback
7442 *
7443 * This function is used to send wake lock stats to HAL layer
7444 *
7445 * Return: 0 on success, error number otherwise.
7446 */
7447static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7448 const struct sir_wake_lock_stats *data)
7449{
7450 struct sk_buff *skb;
7451 uint32_t nl_buf_len;
7452 uint32_t total_rx_data_wake, rx_multicast_cnt;
7453 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307454 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307455
7456 ENTER();
7457
7458 nl_buf_len = NLMSG_HDRLEN;
7459 nl_buf_len +=
7460 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7461 (NLMSG_HDRLEN + sizeof(uint32_t));
7462
7463 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7464
7465 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007466 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307467 return -ENOMEM;
7468 }
7469
Jeff Johnson64943bd2016-08-23 13:14:06 -07007470 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307471 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007472 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307473 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007474 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307475 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007476 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307477 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007478 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307479 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007480 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307481 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007482 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307483 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007484 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7485 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307486 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307487
7488 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307489 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307490
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307491 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307492 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307493
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307494 rx_multicast_cnt =
7495 data->wow_ipv4_mcast_wake_up_count +
7496 ipv6_rx_multicast_addr_cnt;
7497
7498 total_rx_data_wake =
7499 data->wow_ucast_wake_up_count +
7500 data->wow_bcast_wake_up_count +
7501 rx_multicast_cnt;
7502
7503 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7504 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7505 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7506 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7507 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7508 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7509 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7510 total_rx_data_wake) ||
7511 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7512 data->wow_ucast_wake_up_count) ||
7513 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7514 rx_multicast_cnt) ||
7515 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7516 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307517 nla_put_u32(skb, PARAM_ICMP_PKT,
7518 data->wow_icmpv4_count) ||
7519 nla_put_u32(skb, PARAM_ICMP6_PKT,
7520 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307521 nla_put_u32(skb, PARAM_ICMP6_RA,
7522 data->wow_ipv6_mcast_ra_stats) ||
7523 nla_put_u32(skb, PARAM_ICMP6_NA,
7524 data->wow_ipv6_mcast_na_stats) ||
7525 nla_put_u32(skb, PARAM_ICMP6_NS,
7526 data->wow_ipv6_mcast_ns_stats) ||
7527 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7528 data->wow_ipv4_mcast_wake_up_count) ||
7529 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7530 ipv6_rx_multicast_addr_cnt) ||
7531 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007532 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307533 goto nla_put_failure;
7534 }
7535
7536 cfg80211_vendor_cmd_reply(skb);
7537
7538 EXIT();
7539 return 0;
7540
7541nla_put_failure:
7542 kfree_skb(skb);
7543 return -EINVAL;
7544}
7545
7546/**
7547 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7548 * @wiphy: wiphy pointer
7549 * @wdev: pointer to struct wireless_dev
7550 * @data: pointer to incoming NL vendor data
7551 * @data_len: length of @data
7552 *
7553 * This function parses the incoming NL vendor command data attributes and
7554 * invokes the SME Api and blocks on a completion variable.
7555 * WMA copies required data and invokes callback
7556 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7557 *
7558 * Return: 0 on success; error number otherwise.
7559 */
7560static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7561 struct wireless_dev *wdev,
7562 const void *data,
7563 int data_len)
7564{
7565 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7566 int status, ret;
7567 struct sir_wake_lock_stats wake_lock_stats;
7568 QDF_STATUS qdf_status;
7569
7570 ENTER();
7571
7572 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007573 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307574 return -EINVAL;
7575 }
7576
7577 status = wlan_hdd_validate_context(hdd_ctx);
7578 if (0 != status)
7579 return -EINVAL;
7580
7581 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7582 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007583 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307584 return -EINVAL;
7585 }
7586
7587 ret = hdd_send_wakelock_stats(hdd_ctx,
7588 &wake_lock_stats);
7589 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007590 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307591
7592 EXIT();
7593 return ret;
7594}
7595
7596/**
7597 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7598 * @wiphy: wiphy pointer
7599 * @wdev: pointer to struct wireless_dev
7600 * @data: pointer to incoming NL vendor data
7601 * @data_len: length of @data
7602 *
7603 * This function parses the incoming NL vendor command data attributes and
7604 * invokes the SME Api and blocks on a completion variable.
7605 * WMA copies required data and invokes callback
7606 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7607 *
7608 * Return: 0 on success; error number otherwise.
7609 */
7610static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7611 struct wireless_dev *wdev,
7612 const void *data, int data_len)
7613{
7614 int ret;
7615
7616 cds_ssr_protect(__func__);
7617 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7618 data_len);
7619 cds_ssr_protect(__func__);
7620
7621 return ret;
7622}
7623
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307624/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307625 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7626 * @wiphy: wiphy structure pointer
7627 * @wdev: Wireless device structure pointer
7628 * @data: Pointer to the data received
7629 * @data_len: Length of @data
7630 *
7631 * This function reads wmi max bus size and fill in the skb with
7632 * NL attributes and send up the NL event.
7633 * Return: 0 on success; errno on failure
7634 */
7635static int
7636__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7637 struct wireless_dev *wdev,
7638 const void *data, int data_len)
7639{
7640 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7641 int ret_val;
7642 struct sk_buff *skb;
7643 uint32_t nl_buf_len;
7644
7645 ENTER();
7646
7647 ret_val = wlan_hdd_validate_context(hdd_ctx);
7648 if (ret_val)
7649 return ret_val;
7650
7651 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7652 hdd_err("Command not allowed in FTM mode");
7653 return -EINVAL;
7654 }
7655
7656 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7657
7658 nl_buf_len = NLMSG_HDRLEN;
7659 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7660
7661 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7662 if (!skb) {
7663 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7664 return -ENOMEM;
7665 }
7666
7667 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7668 hdd_ctx->wmi_max_len)) {
7669 hdd_err("nla put failure");
7670 goto nla_put_failure;
7671 }
7672
7673 cfg80211_vendor_cmd_reply(skb);
7674
7675 EXIT();
7676
7677 return 0;
7678
7679nla_put_failure:
7680 kfree_skb(skb);
7681 return -EINVAL;
7682}
7683
7684/**
7685 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7686 * @wiphy: wiphy structure pointer
7687 * @wdev: Wireless device structure pointer
7688 * @data: Pointer to the data received
7689 * @data_len: Length of @data
7690 *
7691 * Return: 0 on success; errno on failure
7692 */
7693static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7694 struct wireless_dev *wdev,
7695 const void *data, int data_len)
7696{
7697 int ret;
7698
7699 cds_ssr_protect(__func__);
7700 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7701 cds_ssr_unprotect(__func__);
7702
7703 return ret;
7704}
7705
7706/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307707 *__wlan_hdd_cfg80211_setband() - set band
7708 * @wiphy: Pointer to wireless phy
7709 * @wdev: Pointer to wireless device
7710 * @data: Pointer to data
7711 * @data_len: Length of @data
7712 *
7713 * Return: 0 on success, negative errno on failure
7714 */
7715static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7716 struct wireless_dev *wdev,
7717 const void *data, int data_len)
7718{
7719 struct net_device *dev = wdev->netdev;
7720 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7721 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7722 int ret;
7723 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7724 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7725
7726 ENTER();
7727
7728 ret = wlan_hdd_validate_context(hdd_ctx);
7729 if (ret)
7730 return ret;
7731
7732 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7733 hdd_err(FL("Invalid ATTR"));
7734 return -EINVAL;
7735 }
7736
7737 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7738 hdd_err(FL("attr SETBAND_VALUE failed"));
7739 return -EINVAL;
7740 }
7741
7742 ret = hdd_set_band(dev,
7743 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7744
7745 EXIT();
7746 return ret;
7747}
7748
7749/**
7750 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7751 * @wiphy: wiphy structure pointer
7752 * @wdev: Wireless device structure pointer
7753 * @data: Pointer to the data received
7754 * @data_len: Length of @data
7755 *
7756 * Return: 0 on success; errno on failure
7757 */
7758static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7759 struct wireless_dev *wdev,
7760 const void *data, int data_len)
7761{
7762 int ret;
7763
7764 cds_ssr_protect(__func__);
7765 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7766 cds_ssr_unprotect(__func__);
7767
7768 return ret;
7769}
7770
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307771static const struct
7772nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7773 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7774 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7775 .len = QDF_MAC_ADDR_SIZE},
7776};
7777
7778/**
7779 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7780 * @wiphy: Pointer to wireless phy
7781 * @wdev: Pointer to wireless device
7782 * @data: Pointer to data
7783 * @data_len: Length of @data
7784 *
7785 * This function is used to enable/disable roaming using vendor commands
7786 *
7787 * Return: 0 on success, negative errno on failure
7788 */
7789static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7790 struct wireless_dev *wdev,
7791 const void *data, int data_len)
7792{
7793 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7794 struct net_device *dev = wdev->netdev;
7795 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7796 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7797 uint32_t is_fast_roam_enabled;
7798 int ret;
7799
7800 ENTER_DEV(dev);
7801
7802 ret = wlan_hdd_validate_context(hdd_ctx);
7803 if (0 != ret)
7804 return ret;
7805
7806 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7807 hdd_err("Command not allowed in FTM mode");
7808 return -EINVAL;
7809 }
7810
7811 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7812 qca_wlan_vendor_attr);
7813 if (ret) {
7814 hdd_err("Invalid ATTR");
7815 return -EINVAL;
7816 }
7817
7818 /* Parse and fetch Enable flag */
7819 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7820 hdd_err("attr enable failed");
7821 return -EINVAL;
7822 }
7823
7824 is_fast_roam_enabled = nla_get_u32(
7825 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7826 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7827
7828 /* Update roaming */
7829 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7830 is_fast_roam_enabled);
7831 if (ret)
7832 hdd_err("sme_config_fast_roaming failed");
7833 EXIT();
7834 return ret;
7835}
7836
7837/**
7838 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7839 * @wiphy: Pointer to wireless phy
7840 * @wdev: Pointer to wireless device
7841 * @data: Pointer to data
7842 * @data_len: Length of @data
7843 *
7844 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7845 *
7846 * Return: 0 on success, negative errno on failure
7847 */
7848static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7849 struct wireless_dev *wdev,
7850 const void *data, int data_len)
7851{
7852 int ret;
7853
7854 cds_ssr_protect(__func__);
7855 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7856 cds_ssr_unprotect(__func__);
7857
7858 return ret;
7859}
7860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007861const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7862 {
7863 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7864 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7865 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307866 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007867 .doit = is_driver_dfs_capable
7868 },
7869
7870#ifdef WLAN_FEATURE_NAN
7871 {
7872 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7873 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7874 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7875 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7876 .doit = wlan_hdd_cfg80211_nan_request
7877 },
7878#endif
7879
7880#ifdef WLAN_FEATURE_STATS_EXT
7881 {
7882 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7883 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7884 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7885 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7886 .doit = wlan_hdd_cfg80211_stats_ext_request
7887 },
7888#endif
7889#ifdef FEATURE_WLAN_EXTSCAN
7890 {
7891 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7892 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7893 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7894 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7895 .doit = wlan_hdd_cfg80211_extscan_start
7896 },
7897 {
7898 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7899 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7901 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7902 .doit = wlan_hdd_cfg80211_extscan_stop
7903 },
7904 {
7905 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7906 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7907 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7908 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7909 },
7910 {
7911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7912 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7913 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7914 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7915 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7916 },
7917 {
7918 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7919 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7920 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7921 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7922 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7923 },
7924 {
7925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7928 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7929 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7930 },
7931 {
7932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7934 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7935 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7936 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7937 },
7938 {
7939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7940 .info.subcmd =
7941 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7942 .flags =
7943 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7944 WIPHY_VENDOR_CMD_NEED_RUNNING,
7945 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7946 },
7947 {
7948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7949 .info.subcmd =
7950 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7951 .flags =
7952 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7953 WIPHY_VENDOR_CMD_NEED_RUNNING,
7954 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7955 },
7956 {
7957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7960 WIPHY_VENDOR_CMD_NEED_NETDEV |
7961 WIPHY_VENDOR_CMD_NEED_RUNNING,
7962 .doit = wlan_hdd_cfg80211_set_epno_list
7963 },
7964#endif /* FEATURE_WLAN_EXTSCAN */
7965
7966#ifdef WLAN_FEATURE_LINK_LAYER_STATS
7967 {
7968 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7969 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
7970 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7971 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7972 .doit = wlan_hdd_cfg80211_ll_stats_clear
7973 },
7974
7975 {
7976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7977 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
7978 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7979 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7980 .doit = wlan_hdd_cfg80211_ll_stats_set
7981 },
7982
7983 {
7984 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7985 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
7986 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7987 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7988 .doit = wlan_hdd_cfg80211_ll_stats_get
7989 },
7990#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
7991#ifdef FEATURE_WLAN_TDLS
7992 {
7993 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7994 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
7995 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7996 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7997 .doit = wlan_hdd_cfg80211_exttdls_enable
7998 },
7999 {
8000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8001 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8003 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8004 .doit = wlan_hdd_cfg80211_exttdls_disable
8005 },
8006 {
8007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8010 .doit = wlan_hdd_cfg80211_exttdls_get_status
8011 },
8012#endif
8013 {
8014 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8015 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8016 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8017 .doit = wlan_hdd_cfg80211_get_supported_features
8018 },
8019 {
8020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8021 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8022 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8023 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8024 },
8025 {
8026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308029 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008030 },
8031 {
8032 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8033 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8034 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8035 WIPHY_VENDOR_CMD_NEED_NETDEV,
8036 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8037 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008038 {
8039 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8040 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8042 WIPHY_VENDOR_CMD_NEED_NETDEV,
8043 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8044 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008045 {
8046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8049 WIPHY_VENDOR_CMD_NEED_NETDEV |
8050 WIPHY_VENDOR_CMD_NEED_RUNNING,
8051 .doit = hdd_cfg80211_get_station_cmd
8052 },
8053 {
8054 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008055 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8056 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8057 WIPHY_VENDOR_CMD_NEED_NETDEV |
8058 WIPHY_VENDOR_CMD_NEED_RUNNING,
8059 .doit = wlan_hdd_cfg80211_do_acs
8060 },
8061
8062 {
8063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8066 WIPHY_VENDOR_CMD_NEED_NETDEV,
8067 .doit = wlan_hdd_cfg80211_get_features
8068 },
8069#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8070 {
8071 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8072 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8073 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8074 WIPHY_VENDOR_CMD_NEED_NETDEV |
8075 WIPHY_VENDOR_CMD_NEED_RUNNING,
8076 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8077 },
8078#endif
8079#ifdef FEATURE_WLAN_EXTSCAN
8080 {
8081 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8082 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8083 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8084 WIPHY_VENDOR_CMD_NEED_NETDEV |
8085 WIPHY_VENDOR_CMD_NEED_RUNNING,
8086 .doit = wlan_hdd_cfg80211_set_passpoint_list
8087 },
8088 {
8089 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8090 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8091 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8092 WIPHY_VENDOR_CMD_NEED_NETDEV |
8093 WIPHY_VENDOR_CMD_NEED_RUNNING,
8094 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8095 },
8096 {
8097 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8098 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8099 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8100 WIPHY_VENDOR_CMD_NEED_NETDEV |
8101 WIPHY_VENDOR_CMD_NEED_RUNNING,
8102 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8103 },
8104 {
8105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8106 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8107 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8108 WIPHY_VENDOR_CMD_NEED_NETDEV |
8109 WIPHY_VENDOR_CMD_NEED_RUNNING,
8110 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8111 },
8112#endif /* FEATURE_WLAN_EXTSCAN */
8113 {
8114 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8115 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8116 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8117 WIPHY_VENDOR_CMD_NEED_NETDEV,
8118 .doit = wlan_hdd_cfg80211_get_wifi_info
8119 },
8120 {
8121 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8122 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8123 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8124 WIPHY_VENDOR_CMD_NEED_NETDEV |
8125 WIPHY_VENDOR_CMD_NEED_RUNNING,
8126 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8127 },
8128 {
8129 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8130 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8131 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8132 WIPHY_VENDOR_CMD_NEED_NETDEV,
8133 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8134 },
8135 {
8136 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8137 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8138 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8139 WIPHY_VENDOR_CMD_NEED_NETDEV,
8140 .doit = wlan_hdd_cfg80211_wifi_logger_start
8141 },
8142 {
8143 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8144 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8145 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8146 WIPHY_VENDOR_CMD_NEED_NETDEV,
8147 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8148 },
8149 {
8150 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8151 .info.subcmd =
8152 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8153 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8154 WIPHY_VENDOR_CMD_NEED_NETDEV |
8155 WIPHY_VENDOR_CMD_NEED_RUNNING,
8156 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8157 },
8158 {
8159 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8160 .info.subcmd =
8161 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8162 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8163 WIPHY_VENDOR_CMD_NEED_NETDEV |
8164 WIPHY_VENDOR_CMD_NEED_RUNNING,
8165 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8166 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008167#ifdef WLAN_FEATURE_TSF
8168 {
8169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8170 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8171 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8172 WIPHY_VENDOR_CMD_NEED_NETDEV |
8173 WIPHY_VENDOR_CMD_NEED_RUNNING,
8174 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8175 },
8176#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008177#ifdef FEATURE_WLAN_TDLS
8178 {
8179 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8180 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8181 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8182 WIPHY_VENDOR_CMD_NEED_NETDEV |
8183 WIPHY_VENDOR_CMD_NEED_RUNNING,
8184 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8185 },
8186#endif
8187#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8188 {
8189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8190 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8191 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8192 WIPHY_VENDOR_CMD_NEED_NETDEV |
8193 WIPHY_VENDOR_CMD_NEED_RUNNING,
8194 .doit = wlan_hdd_cfg80211_offloaded_packets
8195 },
8196#endif
8197 {
8198 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8199 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8200 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8201 WIPHY_VENDOR_CMD_NEED_NETDEV |
8202 WIPHY_VENDOR_CMD_NEED_RUNNING,
8203 .doit = wlan_hdd_cfg80211_monitor_rssi
8204 },
8205 {
8206 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308207 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8208 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8209 WIPHY_VENDOR_CMD_NEED_NETDEV |
8210 WIPHY_VENDOR_CMD_NEED_RUNNING,
8211 .doit = wlan_hdd_cfg80211_set_ns_offload
8212 },
8213 {
8214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008215 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8217 WIPHY_VENDOR_CMD_NEED_NETDEV |
8218 WIPHY_VENDOR_CMD_NEED_RUNNING,
8219 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8220 },
8221#ifdef WLAN_FEATURE_MEMDUMP
8222 {
8223 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8224 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8225 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8226 WIPHY_VENDOR_CMD_NEED_NETDEV |
8227 WIPHY_VENDOR_CMD_NEED_RUNNING,
8228 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8229 },
8230#endif /* WLAN_FEATURE_MEMDUMP */
8231 {
8232 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8233 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8234 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8235 WIPHY_VENDOR_CMD_NEED_NETDEV |
8236 WIPHY_VENDOR_CMD_NEED_RUNNING,
8237 .doit = wlan_hdd_cfg80211_vendor_scan
8238 },
8239
8240 /* OCB commands */
8241 {
8242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8245 WIPHY_VENDOR_CMD_NEED_NETDEV |
8246 WIPHY_VENDOR_CMD_NEED_RUNNING,
8247 .doit = wlan_hdd_cfg80211_ocb_set_config
8248 },
8249 {
8250 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8251 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8252 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8253 WIPHY_VENDOR_CMD_NEED_NETDEV |
8254 WIPHY_VENDOR_CMD_NEED_RUNNING,
8255 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8256 },
8257 {
8258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8259 .info.subcmd =
8260 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8261 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8262 WIPHY_VENDOR_CMD_NEED_NETDEV |
8263 WIPHY_VENDOR_CMD_NEED_RUNNING,
8264 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8265 },
8266 {
8267 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8268 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8269 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8270 WIPHY_VENDOR_CMD_NEED_NETDEV |
8271 WIPHY_VENDOR_CMD_NEED_RUNNING,
8272 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8273 },
8274 {
8275 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8276 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8277 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8278 WIPHY_VENDOR_CMD_NEED_NETDEV |
8279 WIPHY_VENDOR_CMD_NEED_RUNNING,
8280 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8281 },
8282 {
8283 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8284 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8285 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8286 WIPHY_VENDOR_CMD_NEED_NETDEV |
8287 WIPHY_VENDOR_CMD_NEED_RUNNING,
8288 .doit = wlan_hdd_cfg80211_dcc_get_stats
8289 },
8290 {
8291 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8292 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8293 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8294 WIPHY_VENDOR_CMD_NEED_NETDEV |
8295 WIPHY_VENDOR_CMD_NEED_RUNNING,
8296 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8297 },
8298 {
8299 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8300 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8301 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8302 WIPHY_VENDOR_CMD_NEED_NETDEV |
8303 WIPHY_VENDOR_CMD_NEED_RUNNING,
8304 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8305 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308306 {
8307 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8308 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8309 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8310 WIPHY_VENDOR_CMD_NEED_NETDEV |
8311 WIPHY_VENDOR_CMD_NEED_RUNNING,
8312 .doit = wlan_hdd_cfg80211_get_link_properties
8313 },
Peng Xu278d0122015-09-24 16:34:17 -07008314 {
Peng Xud2220962016-07-11 17:59:17 -07008315 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008316 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8317 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8318 WIPHY_VENDOR_CMD_NEED_NETDEV |
8319 WIPHY_VENDOR_CMD_NEED_RUNNING,
8320 .doit = wlan_hdd_cfg80211_set_ota_test
8321 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008322#ifdef FEATURE_LFR_SUBNET_DETECTION
8323 {
8324 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8325 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8326 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8327 WIPHY_VENDOR_CMD_NEED_NETDEV |
8328 WIPHY_VENDOR_CMD_NEED_RUNNING,
8329 .doit = wlan_hdd_cfg80211_set_gateway_params
8330 },
8331#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008332 {
Peng Xud2220962016-07-11 17:59:17 -07008333 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008334 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8335 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8336 WIPHY_VENDOR_CMD_NEED_NETDEV |
8337 WIPHY_VENDOR_CMD_NEED_RUNNING,
8338 .doit = wlan_hdd_cfg80211_txpower_scale
8339 },
8340 {
8341 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8342 .info.subcmd =
8343 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8344 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8345 WIPHY_VENDOR_CMD_NEED_NETDEV |
8346 WIPHY_VENDOR_CMD_NEED_RUNNING,
8347 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8348 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308349 {
8350 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8351 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8352 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8353 WIPHY_VENDOR_CMD_NEED_NETDEV |
8354 WIPHY_VENDOR_CMD_NEED_RUNNING,
8355 .doit = wlan_hdd_cfg80211_bpf_offload
8356 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308357 {
8358 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308359 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8360 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8361 WIPHY_VENDOR_CMD_NEED_NETDEV |
8362 WIPHY_VENDOR_CMD_NEED_RUNNING,
8363 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8364 },
8365 {
8366 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308367 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8368 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8369 WIPHY_VENDOR_CMD_NEED_NETDEV |
8370 WIPHY_VENDOR_CMD_NEED_RUNNING,
8371 .doit = wlan_hdd_cfg80211_sta_roam_policy
8372 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308373#ifdef FEATURE_WLAN_CH_AVOID
8374 {
8375 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8376 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8377 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8378 WIPHY_VENDOR_CMD_NEED_NETDEV |
8379 WIPHY_VENDOR_CMD_NEED_RUNNING,
8380 .doit = wlan_hdd_cfg80211_avoid_freq
8381 },
8382#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308383 {
8384 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308385 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8386 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8387 WIPHY_VENDOR_CMD_NEED_NETDEV |
8388 WIPHY_VENDOR_CMD_NEED_RUNNING,
8389 .doit = wlan_hdd_cfg80211_sap_configuration_set
8390 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008391 {
Peng Xu4225c152016-07-14 21:18:14 -07008392 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008393 .info.subcmd =
8394 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8395 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8396 WIPHY_VENDOR_CMD_NEED_NETDEV |
8397 WIPHY_VENDOR_CMD_NEED_RUNNING,
8398 .doit = wlan_hdd_cfg80211_p2p_lo_start
8399 },
8400 {
8401 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8402 .info.subcmd =
8403 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8404 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8405 WIPHY_VENDOR_CMD_NEED_NETDEV |
8406 WIPHY_VENDOR_CMD_NEED_RUNNING,
8407 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8408 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308409 {
8410 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8411 .info.subcmd =
8412 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8413 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8414 WIPHY_VENDOR_CMD_NEED_NETDEV |
8415 WIPHY_VENDOR_CMD_NEED_RUNNING,
8416 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8417 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008418#ifdef WLAN_FEATURE_NAN_DATAPATH
8419 {
8420 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8421 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8422 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8423 WIPHY_VENDOR_CMD_NEED_NETDEV |
8424 WIPHY_VENDOR_CMD_NEED_RUNNING,
8425 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8426 },
8427#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308428 {
8429 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8430 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8431 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8432 WIPHY_VENDOR_CMD_NEED_NETDEV |
8433 WIPHY_VENDOR_CMD_NEED_RUNNING,
8434 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8435 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308436 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308437 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8438 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8439 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8440 WIPHY_VENDOR_CMD_NEED_NETDEV |
8441 WIPHY_VENDOR_CMD_NEED_RUNNING,
8442 .doit = wlan_hdd_cfg80211_get_bus_size
8443 },
8444 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308445 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8446 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8447 WIPHY_VENDOR_CMD_NEED_NETDEV |
8448 WIPHY_VENDOR_CMD_NEED_RUNNING,
8449 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308450 },
8451 {
8452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8455 WIPHY_VENDOR_CMD_NEED_NETDEV |
8456 WIPHY_VENDOR_CMD_NEED_RUNNING,
8457 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308458 },
8459#ifdef WLAN_FEATURE_DISA
8460 {
8461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8462 .info.subcmd =
8463 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8465 WIPHY_VENDOR_CMD_NEED_NETDEV |
8466 WIPHY_VENDOR_CMD_NEED_RUNNING,
8467 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8468 },
8469#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008470};
8471
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008472/**
8473 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8474 * @priv_size: Size of the hdd context.
8475 *
8476 * Allocate wiphy context and hdd context.
8477 *
8478 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008479 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008480hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008481{
8482 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008483 hdd_context_t *hdd_ctx;
8484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008485 ENTER();
8486
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008487 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8488
8489 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008490 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008491 return NULL;
8492 }
8493
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008494 hdd_ctx = wiphy_priv(wiphy);
8495
8496 hdd_ctx->wiphy = wiphy;
8497
8498 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008499}
8500
8501/*
8502 * FUNCTION: wlan_hdd_cfg80211_update_band
8503 * This function is called from the supplicant through a
8504 * private ioctl to change the band value
8505 */
8506int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8507{
8508 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008509 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008510
8511 ENTER();
8512
8513 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8514
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008515 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008516 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008517
8518 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8519 struct ieee80211_supported_band *band = wiphy->bands[i];
8520
8521 channelEnabledState =
8522 cds_get_channel_state(band->channels[j].
8523 hw_value);
8524
8525 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8526 /* 5G only */
8527#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8528 /* Enable Social channels for P2P */
8529 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8530 (band->channels[j].center_freq)
8531 && CHANNEL_STATE_ENABLE ==
8532 channelEnabledState)
8533 band->channels[j].flags &=
8534 ~IEEE80211_CHAN_DISABLED;
8535 else
8536#endif
8537 band->channels[j].flags |=
8538 IEEE80211_CHAN_DISABLED;
8539 continue;
8540 } else if (IEEE80211_BAND_5GHZ == i &&
8541 eCSR_BAND_24 == eBand) {
8542 /* 2G only */
8543 band->channels[j].flags |=
8544 IEEE80211_CHAN_DISABLED;
8545 continue;
8546 }
8547
Amar Singhal6842e8f2016-02-23 16:30:32 -08008548 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008549 band->channels[j].flags &=
8550 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008551 }
8552 }
8553 return 0;
8554}
8555
8556/*
8557 * FUNCTION: wlan_hdd_cfg80211_init
8558 * This function is called by hdd_wlan_startup()
8559 * during initialization.
8560 * This function is used to initialize and register wiphy structure.
8561 */
8562int wlan_hdd_cfg80211_init(struct device *dev,
8563 struct wiphy *wiphy, struct hdd_config *pCfg)
8564{
8565 int i, j;
8566 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8567
8568 ENTER();
8569
8570 /* Now bind the underlying wlan device with wiphy */
8571 set_wiphy_dev(wiphy, dev);
8572
8573 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8574
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8576 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008577 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008578#else
8579 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008580 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008581#endif
8582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008583 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8584 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8585 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8586#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8587 | WIPHY_FLAG_4ADDR_STATION
8588#endif
8589 | WIPHY_FLAG_OFFCHAN_TX;
8590
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008591#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8592 wiphy->wowlan = &wowlan_support_cfg80211_init;
8593#else
8594 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8595 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8596 wiphy->wowlan.pattern_min_len = 1;
8597 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8598#endif
8599
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008600 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008601#ifdef FEATURE_WLAN_ESE
8602 || pCfg->isEseIniFeatureEnabled
8603#endif
8604 ) {
8605 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8606 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008607#ifdef FEATURE_WLAN_TDLS
8608 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8609 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8610#endif
8611
8612 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8613
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8615 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8616#endif
8617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618#ifdef FEATURE_WLAN_SCAN_PNO
8619 if (pCfg->configPNOScanSupport) {
8620 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8621 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8622 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8623 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8625 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8626#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008627 }
8628#endif /*FEATURE_WLAN_SCAN_PNO */
8629
8630#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308631 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008632#endif
8633
8634 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8635 driver can still register regulatory callback and
8636 it will get regulatory settings in wiphy->band[], but
8637 driver need to determine what to do with both
8638 regulatory settings */
8639
8640 wiphy->reg_notifier = hdd_reg_notifier;
8641
8642#if defined QCA_WIFI_FTM
8643}
8644#endif
8645
8646 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8647
8648 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8649
8650 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8651
Arun Khandavallifae92942016-08-01 13:31:08 +05308652 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8653 | BIT(NL80211_IFTYPE_ADHOC)
8654 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8655 | BIT(NL80211_IFTYPE_P2P_GO)
8656 | BIT(NL80211_IFTYPE_AP)
8657 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008658
Arun Khandavallifae92942016-08-01 13:31:08 +05308659 if (pCfg->advertiseConcurrentOperation) {
8660 if (pCfg->enableMCC) {
8661 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008662
Arun Khandavallifae92942016-08-01 13:31:08 +05308663 for (i = 0;
8664 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8665 i++) {
8666 if (!pCfg->allowMCCGODiffBI)
8667 wlan_hdd_iface_combination[i].
8668 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008669 }
8670 }
8671 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308672 ARRAY_SIZE(wlan_hdd_iface_combination);
8673 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008674 }
8675
8676 /* Before registering we need to update the ht capabilitied based
8677 * on ini values*/
8678 if (!pCfg->ShortGI20MhzEnable) {
8679 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8680 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008681 }
8682
8683 if (!pCfg->ShortGI40MhzEnable) {
8684 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8685 }
8686
8687 if (!pCfg->nChannelBondingMode5GHz) {
8688 wlan_hdd_band_5_ghz.ht_cap.cap &=
8689 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8690 }
8691
Abhishek Singhf512bf32016-05-04 16:47:46 +05308692 /*
8693 * In case of static linked driver at the time of driver unload,
8694 * module exit doesn't happens. Module cleanup helps in cleaning
8695 * of static memory.
8696 * If driver load happens statically, at the time of driver unload,
8697 * wiphy flags don't get reset because of static memory.
8698 * It's better not to store channel in static memory.
8699 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008700 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308701 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8702 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8703 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8704 hdd_err("Not enough memory to allocate channels");
8705 return -ENOMEM;
8706 }
8707 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8708 &hdd_channels_2_4_ghz[0],
8709 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308710 if ((hdd_is_5g_supported(pHddCtx)) &&
8711 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8712 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8713 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8714 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008715 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308716 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8717 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8718 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8719 hdd_err("Not enough memory to allocate channels");
8720 qdf_mem_free(wiphy->
8721 bands[IEEE80211_BAND_2GHZ]->channels);
8722 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8723 return -ENOMEM;
8724 }
8725 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8726 &hdd_channels_5_ghz[0],
8727 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008728 }
8729
8730 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8731
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008732 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008733 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008734
8735 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8736 struct ieee80211_supported_band *band = wiphy->bands[i];
8737
8738 if (IEEE80211_BAND_2GHZ == i &&
8739 eCSR_BAND_5G == pCfg->nBandCapability) {
8740 /* 5G only */
8741#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8742 /* Enable social channels for P2P */
8743 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8744 (band->channels[j].center_freq))
8745 band->channels[j].flags &=
8746 ~IEEE80211_CHAN_DISABLED;
8747 else
8748#endif
8749 band->channels[j].flags |=
8750 IEEE80211_CHAN_DISABLED;
8751 continue;
8752 } else if (IEEE80211_BAND_5GHZ == i &&
8753 eCSR_BAND_24 == pCfg->nBandCapability) {
8754 /* 2G only */
8755 band->channels[j].flags |=
8756 IEEE80211_CHAN_DISABLED;
8757 continue;
8758 }
8759 }
8760 }
8761 /*Initialise the supported cipher suite details */
8762 wiphy->cipher_suites = hdd_cipher_suites;
8763 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8764
8765 /*signal strength in mBm (100*dBm) */
8766 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8767 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8768
Anurag Chouhan6d760662016-02-20 16:05:43 +05308769 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008770 wiphy->n_vendor_commands =
8771 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8772 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8773
8774 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8775 wiphy->n_vendor_events =
8776 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8777 }
8778
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008779 if (pCfg->enableDFSMasterCap) {
8780 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8781 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008782
8783 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8784
8785#ifdef QCA_HT_2040_COEX
8786 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8787#endif
8788
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308789 hdd_add_channel_switch_support(&wiphy->flags);
8790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008791 EXIT();
8792 return 0;
8793}
8794
Abhishek Singhf512bf32016-05-04 16:47:46 +05308795/**
8796 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8797 * @ wiphy: the wiphy to validate against
8798 *
8799 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308800 * memory allocated in wlan_hdd_cfg80211_init also
8801 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308802 *
8803 * Return: void
8804 */
8805void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8806{
8807 int i;
8808
8809 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8810 if (NULL != wiphy->bands[i] &&
8811 (NULL != wiphy->bands[i]->channels)) {
8812 qdf_mem_free(wiphy->bands[i]->channels);
8813 wiphy->bands[i]->channels = NULL;
8814 }
8815 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308816 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308817}
8818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008819/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308820 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008821 * initialization. In wlan_hdd_cfg80211_init, only the
8822 * default values will be initialized. The final initialization
8823 * of all required members can be done here.
8824 */
8825void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8826{
8827 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8828}
8829
8830/* In this function we are registering wiphy. */
8831int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8832{
8833 ENTER();
8834 /* Register our wiphy dev with cfg80211 */
8835 if (0 > wiphy_register(wiphy)) {
8836 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008837 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008838 return -EIO;
8839 }
8840
8841 EXIT();
8842 return 0;
8843}
8844
8845/*
8846 HDD function to update wiphy capability based on target offload status.
8847
8848 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8849 capability even before downloading firmware to the target. In discrete
8850 case, host will get know certain offload capability (say sched_scan
8851 caps) only after downloading firmware to the target and target boots up.
8852 This function is used to override setting done in wlan_hdd_cfg80211_init()
8853 based on target capability.
8854 */
8855void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8856{
8857#ifdef FEATURE_WLAN_SCAN_PNO
8858 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8859 struct hdd_config *pCfg = pHddCtx->config;
8860
8861 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8862 * control comes here. Here just we need to clear it if firmware doesn't
8863 * have PNO support. */
8864 if (!pCfg->PnoOffload) {
8865 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8866 wiphy->max_sched_scan_ssids = 0;
8867 wiphy->max_match_sets = 0;
8868 wiphy->max_sched_scan_ie_len = 0;
8869 }
8870#endif
8871}
8872
8873/* This function registers for all frame which supplicant is interested in */
8874void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8875{
8876 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8877 /* Register for all P2P action, public action etc frames */
8878 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8879
8880 ENTER();
8881
Abhishek Singh7996eb72015-12-30 17:24:02 +05308882 /* Register frame indication call back */
8883 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8884
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308885 /* Register for p2p ack indication */
8886 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8887
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008888 /* Right now we are registering these frame when driver is getting
8889 initialized. Once we will move to 2.6.37 kernel, in which we have
8890 frame register ops, we will move this code as a part of that */
8891 /* GAS Initial Request */
8892 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8893 (uint8_t *) GAS_INITIAL_REQ,
8894 GAS_INITIAL_REQ_SIZE);
8895
8896 /* GAS Initial Response */
8897 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8898 (uint8_t *) GAS_INITIAL_RSP,
8899 GAS_INITIAL_RSP_SIZE);
8900
8901 /* GAS Comeback Request */
8902 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8903 (uint8_t *) GAS_COMEBACK_REQ,
8904 GAS_COMEBACK_REQ_SIZE);
8905
8906 /* GAS Comeback Response */
8907 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8908 (uint8_t *) GAS_COMEBACK_RSP,
8909 GAS_COMEBACK_RSP_SIZE);
8910
8911 /* P2P Public Action */
8912 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8913 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8914 P2P_PUBLIC_ACTION_FRAME_SIZE);
8915
8916 /* P2P Action */
8917 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8918 (uint8_t *) P2P_ACTION_FRAME,
8919 P2P_ACTION_FRAME_SIZE);
8920
8921 /* WNM BSS Transition Request frame */
8922 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8923 (uint8_t *) WNM_BSS_ACTION_FRAME,
8924 WNM_BSS_ACTION_FRAME_SIZE);
8925
8926 /* WNM-Notification */
8927 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8928 (uint8_t *) WNM_NOTIFICATION_FRAME,
8929 WNM_NOTIFICATION_FRAME_SIZE);
8930}
8931
8932void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
8933{
8934 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8935 /* Register for all P2P action, public action etc frames */
8936 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8937
8938 ENTER();
8939
8940 /* Right now we are registering these frame when driver is getting
8941 initialized. Once we will move to 2.6.37 kernel, in which we have
8942 frame register ops, we will move this code as a part of that */
8943 /* GAS Initial Request */
8944
8945 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8946 (uint8_t *) GAS_INITIAL_REQ,
8947 GAS_INITIAL_REQ_SIZE);
8948
8949 /* GAS Initial Response */
8950 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8951 (uint8_t *) GAS_INITIAL_RSP,
8952 GAS_INITIAL_RSP_SIZE);
8953
8954 /* GAS Comeback Request */
8955 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8956 (uint8_t *) GAS_COMEBACK_REQ,
8957 GAS_COMEBACK_REQ_SIZE);
8958
8959 /* GAS Comeback Response */
8960 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8961 (uint8_t *) GAS_COMEBACK_RSP,
8962 GAS_COMEBACK_RSP_SIZE);
8963
8964 /* P2P Public Action */
8965 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8966 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8967 P2P_PUBLIC_ACTION_FRAME_SIZE);
8968
8969 /* P2P Action */
8970 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8971 (uint8_t *) P2P_ACTION_FRAME,
8972 P2P_ACTION_FRAME_SIZE);
8973
8974 /* WNM-Notification */
8975 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
8976 (uint8_t *) WNM_NOTIFICATION_FRAME,
8977 WNM_NOTIFICATION_FRAME_SIZE);
8978}
8979
8980#ifdef FEATURE_WLAN_WAPI
8981void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
8982 const uint8_t *mac_addr, const uint8_t *key,
8983 int key_Len)
8984{
8985 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8986 tCsrRoamSetKey setKey;
8987 bool isConnected = true;
8988 int status = 0;
8989 uint32_t roamId = 0xFF;
8990 uint8_t *pKeyPtr = NULL;
8991 int n = 0;
8992
Jeff Johnson46b40792016-06-29 14:03:14 -07008993 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008994 hdd_device_mode_to_string(pAdapter->device_mode),
8995 pAdapter->device_mode);
8996
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308997 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008998 setKey.keyId = key_index; /* Store Key ID */
8999 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9000 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9001 setKey.paeRole = 0; /* the PAE role */
9002 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309003 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009004 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309005 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009006 }
9007 setKey.keyLength = key_Len;
9008 pKeyPtr = setKey.Key;
9009 memcpy(pKeyPtr, key, key_Len);
9010
Jeff Johnson46b40792016-06-29 14:03:14 -07009011 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009012 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009013 hdd_notice("WAPI KEY Data[%d]:%02x ",
9014 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009015
9016 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9017 if (isConnected) {
9018 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9019 pAdapter->sessionId, &setKey, &roamId);
9020 }
9021 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009022 hdd_err("sme_roam_set_key returned ERROR status= %d",
9023 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009024 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9025 }
9026}
9027#endif /* FEATURE_WLAN_WAPI */
9028
9029uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9030 uint8_t eid)
9031{
9032 int left = length;
9033 uint8_t *ptr = (uint8_t *)ies_ptr;
9034 uint8_t elem_id, elem_len;
9035
9036 while (left >= 2) {
9037 elem_id = ptr[0];
9038 elem_len = ptr[1];
9039 left -= 2;
9040 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009041 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009042 eid, elem_len, left);
9043 return NULL;
9044 }
9045 if (elem_id == eid) {
9046 return ptr;
9047 }
9048
9049 left -= elem_len;
9050 ptr += (elem_len + 2);
9051 }
9052 return NULL;
9053}
9054
9055/*
9056 * FUNCTION: wlan_hdd_validate_operation_channel
9057 * called by wlan_hdd_cfg80211_start_bss() and
9058 * wlan_hdd_set_channel()
9059 * This function validates whether given channel is part of valid
9060 * channel list.
9061 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309062QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009063 int channel)
9064{
9065
9066 uint32_t num_ch = 0;
9067 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9068 u32 indx = 0;
9069 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9070 uint8_t fValidChannel = false, count = 0;
9071 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9072
9073 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9074
9075 if (hdd_pConfig_ini->sapAllowAllChannel) {
9076 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009077 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009078 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009079 fValidChannel = true;
9080 break;
9081 }
9082 }
9083 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009084 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309085 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009086 }
9087 } else {
9088 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9089 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009090 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309091 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009092 }
9093 for (indx = 0; indx < num_ch; indx++) {
9094 if (channel == valid_ch[indx]) {
9095 break;
9096 }
9097 }
9098
9099 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009100 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309101 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102 }
9103 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309104 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009105
9106}
9107
9108#ifdef DHCP_SERVER_OFFLOAD
9109static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9110{
9111 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9112 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9113 uint8_t numEntries = 0;
9114 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9115 uint8_t num;
9116 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309117 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009118 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009119 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120 return;
9121 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309122 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009123 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9124 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9125 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9126 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9127 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9128 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009129 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009130 goto end;
9131 }
9132 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009133 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009134 goto end;
9135 }
9136 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009137 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009138 goto end;
9139 }
9140 for (num = 0; num < numEntries; num++) {
9141 temp = srv_ip[num];
9142 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9143 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309144 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009145 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009146 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009147 goto end;
9148 }
Jeff Johnson77848112016-06-29 14:52:06 -07009149 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009150end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309151 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152 return;
9153}
9154#endif /* DHCP_SERVER_OFFLOAD */
9155
9156static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9157 struct net_device *dev,
9158 struct bss_parameters *params)
9159{
9160 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9161 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9162 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309163 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009164
9165 ENTER();
9166
Anurag Chouhan6d760662016-02-20 16:05:43 +05309167 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009168 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009169 return -EINVAL;
9170 }
9171
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309172 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009173 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9174 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009175 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009176 hdd_device_mode_to_string(pAdapter->device_mode),
9177 pAdapter->device_mode, params->ap_isolate);
9178
9179 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9180 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309181 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009182 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183
Krunal Sonib4326f22016-03-10 13:05:51 -08009184 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9185 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009186 return -EOPNOTSUPP;
9187 }
9188
9189 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9190 * want to update this parameter */
9191 if (-1 != params->ap_isolate) {
9192 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9193 !!params->ap_isolate;
9194
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309195 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009196 pAdapter->sessionId,
9197 pAdapter->sessionCtx.
9198 ap.
9199 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309200 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009201 ret = -EINVAL;
9202 }
9203 }
9204
9205 EXIT();
9206 return ret;
9207}
9208
Krunal Soni8c37e322016-02-03 16:08:37 -08009209/**
9210 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9211 * @ndev: pointer to net device provided by supplicant
9212 * @type: type of the interface, upper layer wanted to change
9213 *
9214 * Upper layer provides the new interface mode that needs to be changed
9215 * for given net device
9216 *
9217 * Return: success or failure in terms of integer value
9218 */
9219static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009220 enum nl80211_iftype type)
9221{
Krunal Soni8c37e322016-02-03 16:08:37 -08009222 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9223 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9224 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009225 hdd_wext_state_t *wext;
9226 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309227 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009228
9229 ENTER();
9230
Krunal Soni8c37e322016-02-03 16:08:37 -08009231 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009232 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009233 return 0;
9234 }
9235
9236 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009237 hdd_stop_adapter(hdd_ctx, adapter, true);
9238 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009239 wdev->iftype = type;
9240 /*Check for sub-string p2p to confirm its a p2p interface */
9241 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009242 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009243 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009244 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009245 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009246 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009247 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009248 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009249 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009250 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009251 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009252 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9253 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009254 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9255 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009256 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009257 adapter->scan_info.scanAddIE.length;
9258 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309259 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009260 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9261 wext->roamProfile.phyMode =
9262 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9263 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264 EXIT();
9265 return status;
9266}
9267
9268static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9269 struct net_device *dev,
9270 struct bss_parameters *params)
9271{
9272 int ret;
9273
9274 cds_ssr_protect(__func__);
9275 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9276 cds_ssr_unprotect(__func__);
9277
9278 return ret;
9279}
9280
9281/* FUNCTION: wlan_hdd_change_country_code_cd
9282 * to wait for contry code completion
9283 */
9284void *wlan_hdd_change_country_code_cb(void *pAdapter)
9285{
9286 hdd_adapter_t *call_back_pAdapter = pAdapter;
9287 complete(&call_back_pAdapter->change_country_code);
9288 return NULL;
9289}
9290
Rajeev Kumar98edb772016-01-19 12:42:19 -08009291/**
9292 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9293 * @wiphy: Pointer to the wiphy structure
9294 * @ndev: Pointer to the net device
9295 * @type: Interface type
9296 * @flags: Flags for change interface
9297 * @params: Pointer to change interface parameters
9298 *
9299 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009300 */
9301static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9302 struct net_device *ndev,
9303 enum nl80211_iftype type,
9304 u32 *flags,
9305 struct vif_params *params)
9306{
9307 struct wireless_dev *wdev;
9308 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9309 hdd_context_t *pHddCtx;
9310 tCsrRoamProfile *pRoamProfile = NULL;
9311 eCsrRoamBssType LastBSSType;
9312 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309313 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009314 int status;
9315
9316 ENTER();
9317
Anurag Chouhan6d760662016-02-20 16:05:43 +05309318 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009319 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009320 return -EINVAL;
9321 }
9322
9323 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9324 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309325 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009326 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009327
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309328 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009329 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9330 pAdapter->sessionId, type));
9331
Jeff Johnson77848112016-06-29 14:52:06 -07009332 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009333 pAdapter->device_mode, type);
9334
Arun Khandavallifae92942016-08-01 13:31:08 +05309335 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9336 if (status) {
9337 hdd_err("Failed to start modules");
9338 return -EINVAL;
9339 }
9340
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009341 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9343 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009344 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009345 return -EINVAL;
9346 }
9347
9348 pConfig = pHddCtx->config;
9349 wdev = ndev->ieee80211_ptr;
9350
9351 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009352 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009353
9354 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9355
Krunal Sonib4326f22016-03-10 13:05:51 -08009356 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9357 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9358 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9359 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009360 hdd_wext_state_t *pWextState =
9361 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9362
9363 pRoamProfile = &pWextState->roamProfile;
9364 LastBSSType = pRoamProfile->BSSType;
9365
9366 switch (type) {
9367 case NL80211_IFTYPE_STATION:
9368 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009369 case NL80211_IFTYPE_ADHOC:
9370 if (type == NL80211_IFTYPE_ADHOC) {
9371 wlan_hdd_tdls_exit(pAdapter);
9372 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009373 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009374 }
9375 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9376 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309377 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009378 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309379 if (hdd_start_adapter(pAdapter)) {
9380 hdd_err("Failed to start adapter :%d",
9381 pAdapter->device_mode);
9382 return -EINVAL;
9383 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009384 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385 case NL80211_IFTYPE_AP:
9386 case NL80211_IFTYPE_P2P_GO:
9387 {
Jeff Johnson77848112016-06-29 14:52:06 -07009388 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009389 (type ==
9390 NL80211_IFTYPE_AP) ? "SoftAP" :
9391 "P2pGo");
9392
9393 /* Cancel any remain on channel for GO mode */
9394 if (NL80211_IFTYPE_P2P_GO == type) {
9395 wlan_hdd_cancel_existing_remain_on_channel
9396 (pAdapter);
9397 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398
Arun Khandavallifae92942016-08-01 13:31:08 +05309399 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400 /* De-init the adapter */
9401 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9402 memset(&pAdapter->sessionCtx, 0,
9403 sizeof(pAdapter->sessionCtx));
9404 pAdapter->device_mode =
9405 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009406 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9407 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009408
9409 /*
9410 * Fw will take care incase of concurrency
9411 */
9412
Krunal Sonib4326f22016-03-10 13:05:51 -08009413 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414 && (pConfig->apRandomBssidEnabled)) {
9415 /* To meet Android requirements create a randomized
9416 MAC address of the form 02:1A:11:Fx:xx:xx */
9417 get_random_bytes(&ndev->dev_addr[3], 3);
9418 ndev->dev_addr[0] = 0x02;
9419 ndev->dev_addr[1] = 0x1A;
9420 ndev->dev_addr[2] = 0x11;
9421 ndev->dev_addr[3] |= 0xF0;
9422 memcpy(pAdapter->macAddressCurrent.
9423 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309424 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425 pr_info("wlan: Generated HotSpot BSSID "
9426 MAC_ADDRESS_STR "\n",
9427 MAC_ADDR_ARRAY(ndev->dev_addr));
9428 }
9429
9430 hdd_set_ap_ops(pAdapter->dev);
9431
Arun Khandavallifae92942016-08-01 13:31:08 +05309432 if (hdd_start_adapter(pAdapter)) {
9433 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009434 return -EINVAL;
9435 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436 /* Interface type changed update in wiphy structure */
9437 if (wdev) {
9438 wdev->iftype = type;
9439 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009440 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009441 return -EINVAL;
9442 }
9443 goto done;
9444 }
9445
9446 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009447 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009448 type);
9449 return -EOPNOTSUPP;
9450 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009451 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9452 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009453 switch (type) {
9454 case NL80211_IFTYPE_STATION:
9455 case NL80211_IFTYPE_P2P_CLIENT:
9456 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009457 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9458 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309459 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009460 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309461 if (hdd_start_adapter(pAdapter)) {
9462 hdd_err("Failed to start adapter :%d",
9463 pAdapter->device_mode);
9464 return -EINVAL;
9465 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009466 goto done;
9467
9468 case NL80211_IFTYPE_AP:
9469 case NL80211_IFTYPE_P2P_GO:
9470 wdev->iftype = type;
9471 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009472 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473 goto done;
9474
9475 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009476 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009477 type);
9478 return -EOPNOTSUPP;
9479 }
9480 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009481 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009482 pAdapter->device_mode);
9483 return -EOPNOTSUPP;
9484 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485done:
9486 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009487 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009488
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009489 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009490
9491 EXIT();
9492 return 0;
9493}
9494
Rajeev Kumar98edb772016-01-19 12:42:19 -08009495/**
9496 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9497 * @wiphy: Pointer to the wiphy structure
9498 * @ndev: Pointer to the net device
9499 * @type: Interface type
9500 * @flags: Flags for change interface
9501 * @params: Pointer to change interface parameters
9502 *
9503 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504 */
9505static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9506 struct net_device *ndev,
9507 enum nl80211_iftype type,
9508 u32 *flags,
9509 struct vif_params *params)
9510{
9511 int ret;
9512
9513 cds_ssr_protect(__func__);
9514 ret =
9515 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9516 cds_ssr_unprotect(__func__);
9517
9518 return ret;
9519}
9520
9521#ifdef FEATURE_WLAN_TDLS
9522static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9523 int index, uint8_t match)
9524{
9525 int i;
9526 for (i = 0; i < index; i++) {
9527 if (arr[i] == match)
9528 return true;
9529 }
9530 return false;
9531}
9532#endif
9533
9534/**
9535 * __wlan_hdd_change_station() - change station
9536 * @wiphy: Pointer to the wiphy structure
9537 * @dev: Pointer to the net device.
9538 * @mac: bssid
9539 * @params: Pointer to station parameters
9540 *
9541 * Return: 0 for success, error number on failure.
9542 */
9543#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9544static int __wlan_hdd_change_station(struct wiphy *wiphy,
9545 struct net_device *dev,
9546 const uint8_t *mac,
9547 struct station_parameters *params)
9548#else
9549static int __wlan_hdd_change_station(struct wiphy *wiphy,
9550 struct net_device *dev,
9551 uint8_t *mac,
9552 struct station_parameters *params)
9553#endif
9554{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309555 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009556 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9557 hdd_context_t *pHddCtx;
9558 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309559 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009560#ifdef FEATURE_WLAN_TDLS
9561 tCsrStaParams StaParams = { 0 };
9562 uint8_t isBufSta = 0;
9563 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309564 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009565#endif
9566 int ret;
9567
9568 ENTER();
9569
Anurag Chouhan6d760662016-02-20 16:05:43 +05309570 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009571 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009572 return -EINVAL;
9573 }
9574
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309575 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009576 TRACE_CODE_HDD_CHANGE_STATION,
9577 pAdapter->sessionId, params->listen_interval));
9578
9579 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9580 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309581 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009582 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009583
9584 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9585
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309586 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009587
Krunal Sonib4326f22016-03-10 13:05:51 -08009588 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9589 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009590 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9591 status =
9592 hdd_softap_change_sta_state(pAdapter,
9593 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009594 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309596 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009597 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009598 return -EINVAL;
9599 }
9600 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009601 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9602 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603#ifdef FEATURE_WLAN_TDLS
9604 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009605
9606 if (cds_is_sub_20_mhz_enabled()) {
9607 hdd_err("TDLS not allowed with sub 20 MHz");
9608 return -EINVAL;
9609 }
9610
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009611 StaParams.capability = params->capability;
9612 StaParams.uapsd_queues = params->uapsd_queues;
9613 StaParams.max_sp = params->max_sp;
9614
9615 /* Convert (first channel , number of channels) tuple to
9616 * the total list of channels. This goes with the assumption
9617 * that if the first channel is < 14, then the next channels
9618 * are an incremental of 1 else an incremental of 4 till the number
9619 * of channels.
9620 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009621 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009622 if (0 != params->supported_channels_len) {
9623 int i = 0, j = 0, k = 0, no_of_channels = 0;
9624 int num_unique_channels;
9625 int next;
9626 for (i = 0;
9627 i < params->supported_channels_len
9628 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9629 int wifi_chan_index;
9630 if (!wlan_hdd_is_duplicate_channel
9631 (StaParams.supported_channels, j,
9632 params->supported_channels[i])) {
9633 StaParams.
9634 supported_channels[j] =
9635 params->
9636 supported_channels[i];
9637 } else {
9638 continue;
9639 }
9640 wifi_chan_index =
9641 ((StaParams.supported_channels[j] <=
9642 HDD_CHANNEL_14) ? 1 : 4);
9643 no_of_channels =
9644 params->supported_channels[i + 1];
9645
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009646 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d", i, j, k, j,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009647 StaParams.
9648 supported_channels[j],
9649 wifi_chan_index,
9650 no_of_channels);
9651 for (k = 1; k <= no_of_channels &&
9652 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9653 k++) {
9654 next =
9655 StaParams.
9656 supported_channels[j] +
9657 wifi_chan_index;
9658 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9659 StaParams.
9660 supported_channels[j
9661 +
9662 1]
9663 = next;
9664 } else {
9665 continue;
9666 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009667 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009668 j + 1,
9669 StaParams.
9670 supported_channels[j +
9671 1]);
9672 j += 1;
9673 }
9674 }
9675 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009676 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009677 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009678 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009679 StaParams.
9680 supported_channels[i]);
9681 }
9682 if (MAX_CHANNEL < num_unique_channels)
9683 num_unique_channels = MAX_CHANNEL;
9684 StaParams.supported_channels_len =
9685 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009686 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009687 StaParams.supported_channels_len);
9688 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309689 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690 params->supported_oper_classes,
9691 params->supported_oper_classes_len);
9692 StaParams.supported_oper_classes_len =
9693 params->supported_oper_classes_len;
9694
9695 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309696 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009697 params->ext_capab,
9698 sizeof(StaParams.extn_capability));
9699
9700 if (NULL != params->ht_capa) {
9701 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309702 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009703 sizeof(tSirHTCap));
9704 }
9705
9706 StaParams.supported_rates_len =
9707 params->supported_rates_len;
9708
9709 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9710 * The supported_rates array , for all the structures propogating till Add Sta
9711 * to the firmware has to be modified , if the supplicant (ieee80211) is
9712 * modified to send more rates.
9713 */
9714
9715 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9716 */
9717 if (StaParams.supported_rates_len >
9718 SIR_MAC_MAX_SUPP_RATES)
9719 StaParams.supported_rates_len =
9720 SIR_MAC_MAX_SUPP_RATES;
9721
9722 if (0 != StaParams.supported_rates_len) {
9723 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309724 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009725 params->supported_rates,
9726 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009727 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009728 StaParams.supported_rates_len);
9729 for (i = 0; i < StaParams.supported_rates_len;
9730 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009731 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732 StaParams.supported_rates[i]);
9733 }
9734
9735 if (NULL != params->vht_capa) {
9736 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309737 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009738 params->vht_capa,
9739 sizeof(tSirVHTCap));
9740 }
9741
9742 if (0 != params->ext_capab_len) {
9743 /*Define A Macro : TODO Sunil */
9744 if ((1 << 4) & StaParams.extn_capability[3]) {
9745 isBufSta = 1;
9746 }
9747 /* TDLS Channel Switching Support */
9748 if ((1 << 6) & StaParams.extn_capability[3]) {
9749 isOffChannelSupported = 1;
9750 }
9751 }
9752
Nitesh Shah99934ac2016-09-05 15:54:08 +05309753 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309754 (params->ht_capa || params->vht_capa ||
9755 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309756 is_qos_wmm_sta = true;
9757
9758 hdd_notice("%s: TDLS Peer is QOS capable"
9759 " is_qos_wmm_sta= %d HTcapPresent = %d",
9760 __func__, is_qos_wmm_sta,
9761 StaParams.htcap_present);
9762
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009763 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309764 &StaParams,
9765 isBufSta,
9766 isOffChannelSupported,
9767 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309768 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009769 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009770 return -EINVAL;
9771 }
9772
9773 status =
9774 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9775 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309776 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009777 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009778 return -EINVAL;
9779 }
9780 }
9781#endif
9782 }
9783 EXIT();
9784 return ret;
9785}
9786
9787/**
9788 * wlan_hdd_change_station() - cfg80211 change station handler function
9789 * @wiphy: Pointer to the wiphy structure
9790 * @dev: Pointer to the net device.
9791 * @mac: bssid
9792 * @params: Pointer to station parameters
9793 *
9794 * This is the cfg80211 change station handler function which invokes
9795 * the internal function @__wlan_hdd_change_station with
9796 * SSR protection.
9797 *
9798 * Return: 0 for success, error number on failure.
9799 */
9800#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9801static int wlan_hdd_change_station(struct wiphy *wiphy,
9802 struct net_device *dev,
9803 const u8 *mac,
9804 struct station_parameters *params)
9805#else
9806static int wlan_hdd_change_station(struct wiphy *wiphy,
9807 struct net_device *dev,
9808 u8 *mac,
9809 struct station_parameters *params)
9810#endif
9811{
9812 int ret;
9813
9814 cds_ssr_protect(__func__);
9815 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9816 cds_ssr_unprotect(__func__);
9817
9818 return ret;
9819}
9820
9821/*
9822 * FUNCTION: __wlan_hdd_cfg80211_add_key
9823 * This function is used to initialize the key information
9824 */
9825static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9826 struct net_device *ndev,
9827 u8 key_index, bool pairwise,
9828 const u8 *mac_addr,
9829 struct key_params *params)
9830{
9831 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9832 tCsrRoamSetKey setKey;
9833 int status;
9834 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009835 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309836 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009837 hdd_context_t *pHddCtx;
9838 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9839
9840 ENTER();
9841
Anurag Chouhan6d760662016-02-20 16:05:43 +05309842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009843 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009844 return -EINVAL;
9845 }
9846
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309847 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009848 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9849 pAdapter->sessionId, params->key_len));
9850 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9851 status = wlan_hdd_validate_context(pHddCtx);
9852
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309853 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009855
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009856 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009857 hdd_device_mode_to_string(pAdapter->device_mode),
9858 pAdapter->device_mode);
9859
9860 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009861 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009862
9863 return -EINVAL;
9864 }
9865
9866 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009867 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868
9869 return -EINVAL;
9870 }
9871
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009872 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009873
9874 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309875 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009876 setKey.keyId = key_index;
9877 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309878 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009879
9880 switch (params->cipher) {
9881 case WLAN_CIPHER_SUITE_WEP40:
9882 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9883 break;
9884
9885 case WLAN_CIPHER_SUITE_WEP104:
9886 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9887 break;
9888
9889 case WLAN_CIPHER_SUITE_TKIP:
9890 {
9891 u8 *pKey = &setKey.Key[0];
9892 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9893
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309894 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009895
9896 /*Supplicant sends the 32bytes key in this order
9897
9898 |--------------|----------|----------|
9899 | Tk1 |TX-MIC | RX Mic |
9900 |||--------------|----------|----------|
9901 <---16bytes---><--8bytes--><--8bytes-->
9902
9903 */
9904 /*Sme expects the 32 bytes key to be in the below order
9905
9906 |--------------|----------|----------|
9907 | Tk1 |RX-MIC | TX Mic |
9908 |||--------------|----------|----------|
9909 <---16bytes---><--8bytes--><--8bytes-->
9910 */
9911 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309912 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009913
9914 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309915 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009916
9917 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309918 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009919
9920 break;
9921 }
9922
9923 case WLAN_CIPHER_SUITE_CCMP:
9924 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9925 break;
9926
9927#ifdef FEATURE_WLAN_WAPI
9928 case WLAN_CIPHER_SUITE_SMS4:
9929 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309930 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009931 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9932 mac_addr, params->key,
9933 params->key_len);
9934 return 0;
9935 }
9936#endif
9937
9938#ifdef FEATURE_WLAN_ESE
9939 case WLAN_CIPHER_SUITE_KRK:
9940 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9941 break;
9942#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9943 case WLAN_CIPHER_SUITE_BTK:
9944 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9945 break;
9946#endif
9947#endif
9948
9949#ifdef WLAN_FEATURE_11W
9950 case WLAN_CIPHER_SUITE_AES_CMAC:
9951 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9952 break;
9953#endif
9954
9955 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009956 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 return -EOPNOTSUPP;
9958 }
9959
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009960 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961
9962 if (!pairwise) {
9963 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009964 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009965 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309966 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009967 } else {
9968 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009969 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009970 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309971 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009973 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009974 /* if a key is already installed, block all subsequent ones */
9975 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009976 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009977 return 0;
9978 }
9979
9980 setKey.keyDirection = eSIR_TX_RX;
9981 /*Set the group key */
9982 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9983 pAdapter->sessionId, &setKey, &roamId);
9984
9985 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009986 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009987 return -EINVAL;
9988 }
9989 /*Save the keys here and call sme_roam_set_key for setting
9990 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309991 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 &setKey, sizeof(tCsrRoamSetKey));
9993
9994 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
9995 return status;
9996 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009997 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9998 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009999 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10000 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010001 status = wlansap_set_key_sta(
10002 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010003 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010004 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005 __LINE__, status);
10006 }
10007 }
10008
10009 /* Save the key in ap ctx for use on START_BASS and restart */
10010 if (pairwise ||
10011 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10012 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010013 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010014 sizeof(tCsrRoamSetKey));
10015 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010016 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 sizeof(tCsrRoamSetKey));
10018
Krunal Sonib4326f22016-03-10 13:05:51 -080010019 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10020 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021 hdd_wext_state_t *pWextState =
10022 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10023 hdd_station_ctx_t *pHddStaCtx =
10024 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10025
10026 if (!pairwise) {
10027 /* set group key */
10028 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010029 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010030 __func__, __LINE__);
10031 hdd_perform_roam_set_key_complete(pAdapter);
10032 }
10033 }
10034
10035 pWextState->roamProfile.Keys.KeyLength[key_index] =
10036 (u8) params->key_len;
10037
10038 pWextState->roamProfile.Keys.defaultIndex = key_index;
10039
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010040 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041 KeyMaterial[key_index][0], params->key,
10042 params->key_len);
10043
10044 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10045
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010046 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010047 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10048 setKey.keyDirection);
10049
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010050 /* The supplicant may attempt to set the PTK once pre-authentication
10051 is done. Save the key in the UMAC and include it in the ADD BSS
10052 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010053 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010055 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010056 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010057 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010058 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010059 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010060 return -EINVAL;
10061 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010062
10063 /* issue set key request to SME */
10064 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10065 pAdapter->sessionId, &setKey, &roamId);
10066
10067 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010068 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010069 pHddStaCtx->roam_info.roamingState =
10070 HDD_ROAM_STATE_NONE;
10071 return -EINVAL;
10072 }
10073
10074 /* in case of IBSS as there was no information available about WEP keys during
10075 * IBSS join, group key intialized with NULL key, so re-initialize group key
10076 * with correct value*/
10077 if ((eCSR_BSS_TYPE_START_IBSS ==
10078 pWextState->roamProfile.BSSType)
10079 &&
10080 !((IW_AUTH_KEY_MGMT_802_1X ==
10081 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10082 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10083 pHddStaCtx->conn_info.authType)
10084 )
10085 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10086 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10087 )
10088 ) {
10089 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010090 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010091
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010092 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10094 setKey.keyDirection);
10095
10096 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10097 pAdapter->sessionId, &setKey,
10098 &roamId);
10099
10100 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010101 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102 pHddStaCtx->roam_info.roamingState =
10103 HDD_ROAM_STATE_NONE;
10104 return -EINVAL;
10105 }
10106 }
10107 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010108 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 return 0;
10110}
10111
10112static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10113 struct net_device *ndev,
10114 u8 key_index, bool pairwise,
10115 const u8 *mac_addr,
10116 struct key_params *params)
10117{
10118 int ret;
10119 cds_ssr_protect(__func__);
10120 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10121 mac_addr, params);
10122 cds_ssr_unprotect(__func__);
10123
10124 return ret;
10125}
10126
10127/*
10128 * FUNCTION: __wlan_hdd_cfg80211_get_key
10129 * This function is used to get the key information
10130 */
10131static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10132 struct net_device *ndev,
10133 u8 key_index, bool pairwise,
10134 const u8 *mac_addr, void *cookie,
10135 void (*callback)(void *cookie,
10136 struct key_params *)
10137 )
10138{
10139 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10140 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10141 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10142 struct key_params params;
10143
10144 ENTER();
10145
Anurag Chouhan6d760662016-02-20 16:05:43 +053010146 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010147 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148 return -EINVAL;
10149 }
10150
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010151 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010152 hdd_device_mode_to_string(pAdapter->device_mode),
10153 pAdapter->device_mode);
10154
10155 memset(&params, 0, sizeof(params));
10156
10157 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010158 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010159 key_index);
10160 return -EINVAL;
10161 }
10162
10163 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10164 case eCSR_ENCRYPT_TYPE_NONE:
10165 params.cipher = IW_AUTH_CIPHER_NONE;
10166 break;
10167
10168 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10169 case eCSR_ENCRYPT_TYPE_WEP40:
10170 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10171 break;
10172
10173 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10174 case eCSR_ENCRYPT_TYPE_WEP104:
10175 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10176 break;
10177
10178 case eCSR_ENCRYPT_TYPE_TKIP:
10179 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10180 break;
10181
10182 case eCSR_ENCRYPT_TYPE_AES:
10183 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10184 break;
10185
10186 default:
10187 params.cipher = IW_AUTH_CIPHER_NONE;
10188 break;
10189 }
10190
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010191 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010192 TRACE_CODE_HDD_CFG80211_GET_KEY,
10193 pAdapter->sessionId, params.cipher));
10194
10195 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10196 params.seq_len = 0;
10197 params.seq = NULL;
10198 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10199 callback(cookie, &params);
10200
10201 EXIT();
10202 return 0;
10203}
10204
10205static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10206 struct net_device *ndev,
10207 u8 key_index, bool pairwise,
10208 const u8 *mac_addr, void *cookie,
10209 void (*callback)(void *cookie,
10210 struct key_params *)
10211 )
10212{
10213 int ret;
10214
10215 cds_ssr_protect(__func__);
10216 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10217 mac_addr, cookie, callback);
10218 cds_ssr_unprotect(__func__);
10219
10220 return ret;
10221}
10222
10223/**
10224 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10225 * @wiphy: wiphy interface context
10226 * @ndev: pointer to net device
10227 * @key_index: Key index used in 802.11 frames
10228 * @unicast: true if it is unicast key
10229 * @multicast: true if it is multicast key
10230 *
10231 * This function is required for cfg80211_ops API.
10232 * It is used to delete the key information
10233 * Underlying hardware implementation does not have API to delete the
10234 * encryption key. It is automatically deleted when the peer is
10235 * removed. Hence this function currently does nothing.
10236 * Future implementation may interprete delete key operation to
10237 * replacing the key with a random junk value, effectively making it
10238 * useless.
10239 *
10240 * Return: status code, always 0.
10241 */
10242
10243static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10244 struct net_device *ndev,
10245 u8 key_index,
10246 bool pairwise, const u8 *mac_addr)
10247{
10248 EXIT();
10249 return 0;
10250}
10251
10252/**
10253 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10254 * @wiphy: Pointer to wiphy structure.
10255 * @dev: Pointer to net_device structure.
10256 * @key_index: key index
10257 * @pairwise: pairwise
10258 * @mac_addr: mac address
10259 *
10260 * This is the cfg80211 delete key handler function which invokes
10261 * the internal function @__wlan_hdd_cfg80211_del_key with
10262 * SSR protection.
10263 *
10264 * Return: 0 for success, error number on failure.
10265 */
10266static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10267 struct net_device *dev,
10268 u8 key_index,
10269 bool pairwise, const u8 *mac_addr)
10270{
10271 int ret;
10272
10273 cds_ssr_protect(__func__);
10274 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10275 pairwise, mac_addr);
10276 cds_ssr_unprotect(__func__);
10277
10278 return ret;
10279}
10280
10281/*
10282 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10283 * This function is used to set the default tx key index
10284 */
10285static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10286 struct net_device *ndev,
10287 u8 key_index,
10288 bool unicast, bool multicast)
10289{
10290 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10291 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10292 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10293 hdd_context_t *pHddCtx;
10294 int status;
10295
10296 ENTER();
10297
Anurag Chouhan6d760662016-02-20 16:05:43 +053010298 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010299 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010300 return -EINVAL;
10301 }
10302
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010303 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10305 pAdapter->sessionId, key_index));
10306
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010307 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010308 hdd_device_mode_to_string(pAdapter->device_mode),
10309 pAdapter->device_mode, key_index);
10310
10311 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010312 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010313 return -EINVAL;
10314 }
10315
10316 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10317 status = wlan_hdd_validate_context(pHddCtx);
10318
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010319 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010320 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010321
Krunal Sonib4326f22016-03-10 13:05:51 -080010322 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10323 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10325 pHddStaCtx->conn_info.ucEncryptionType) &&
10326 (eCSR_ENCRYPT_TYPE_AES !=
10327 pHddStaCtx->conn_info.ucEncryptionType)) {
10328 /* If default key index is not same as previous one,
10329 * then update the default key index */
10330
10331 tCsrRoamSetKey setKey;
10332 uint32_t roamId = 0xFF;
10333 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10334
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010335 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010336
10337 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010338 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010339 setKey.keyId = key_index;
10340 setKey.keyLength = Keys->KeyLength[key_index];
10341
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010342 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343 &Keys->KeyMaterial[key_index][0],
10344 Keys->KeyLength[key_index]);
10345
10346 setKey.keyDirection = eSIR_TX_RX;
10347
Anurag Chouhanc5548422016-02-24 18:33:27 +053010348 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010349 &pHddStaCtx->conn_info.bssId);
10350
10351 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10352 pWextState->roamProfile.EncryptionType.
10353 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10354 /* In the case of dynamic wep supplicant hardcodes DWEP type
10355 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10356 * WEP-40 encryption. In this canse the key length is 5 but the
10357 * encryption type is 104 hence checking the key langht(5) and
10358 * encryption type(104) and switching encryption type to 40*/
10359 pWextState->roamProfile.EncryptionType.
10360 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10361 pWextState->roamProfile.mcEncryptionType.
10362 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10363 }
10364
10365 setKey.encType =
10366 pWextState->roamProfile.EncryptionType.
10367 encryptionType[0];
10368
10369 /* Issue set key request */
10370 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10371 pAdapter->sessionId, &setKey,
10372 &roamId);
10373
10374 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010375 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 status);
10377 return -EINVAL;
10378 }
10379 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010380 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010381 /* In SoftAp mode setting key direction for default mode */
10382 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10383 pWextState->roamProfile.EncryptionType.encryptionType[0])
10384 && (eCSR_ENCRYPT_TYPE_AES !=
10385 pWextState->roamProfile.EncryptionType.
10386 encryptionType[0])) {
10387 /* Saving key direction for default key index to TX default */
10388 hdd_ap_ctx_t *pAPCtx =
10389 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10390 pAPCtx->wepKey[key_index].keyDirection =
10391 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010392 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010393 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010394 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010395 }
10396 }
10397
10398 EXIT();
10399 return status;
10400}
10401
10402static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10403 struct net_device *ndev,
10404 u8 key_index,
10405 bool unicast, bool multicast)
10406{
10407 int ret;
10408 cds_ssr_protect(__func__);
10409 ret =
10410 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10411 multicast);
10412 cds_ssr_unprotect(__func__);
10413
10414 return ret;
10415}
10416
Abhishek Singhc9941602016-08-09 16:06:22 +053010417/*
10418 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10419 * @wiphy: wiphy pointer
10420 * @channel: channel of the BSS
10421 * @bssid: Bssid of BSS
10422 * @ssid: Ssid of the BSS
10423 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010424 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010425 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010427#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010428static
Abhishek Singhc9941602016-08-09 16:06:22 +053010429struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10430 struct ieee80211_channel *channel, const u8 *bssid,
10431 const u8 *ssid, size_t ssid_len)
10432{
10433 return cfg80211_get_bss(wiphy, channel, bssid,
10434 ssid,
10435 ssid_len,
10436 WLAN_CAPABILITY_ESS,
10437 WLAN_CAPABILITY_ESS);
10438}
10439#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010440static
Abhishek Singhc9941602016-08-09 16:06:22 +053010441struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10442 struct ieee80211_channel *channel, const u8 *bssid,
10443 const u8 *ssid, size_t ssid_len)
10444{
10445 return cfg80211_get_bss(wiphy, channel, bssid,
10446 ssid,
10447 ssid_len,
10448 IEEE80211_BSS_TYPE_ESS,
10449 IEEE80211_PRIVACY_ANY);
10450}
10451#endif
10452
10453
10454/*
10455 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10456 * interface that BSS might have been lost.
10457 * @pAdapter: adaptor
10458 * @bssid: bssid which might have been lost
10459 *
10460 * Return: bss which is unlinked from kernel cache
10461 */
10462struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10463 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010464{
10465 struct net_device *dev = pAdapter->dev;
10466 struct wireless_dev *wdev = dev->ieee80211_ptr;
10467 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010468 struct cfg80211_bss *bss = NULL;
10469
Abhishek Singhc9941602016-08-09 16:06:22 +053010470 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10471 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010472 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010473 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010475 hdd_info("cfg80211_unlink_bss called for BSSID "
10476 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010477 cfg80211_unlink_bss(wiphy, bss);
10478 }
10479 return bss;
10480}
10481
Abhishek Singhc9941602016-08-09 16:06:22 +053010482
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010483/**
10484 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10485 * @pAdapter: Pointer to adapter
10486 * @bss_desc: Pointer to bss descriptor
10487 *
10488 * This function is used to inform the BSS details to nl80211 interface.
10489 *
10490 * Return: struct cfg80211_bss pointer
10491 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010492struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10493 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010494{
10495 /*
10496 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10497 * already exists in bss data base of cfg80211 for that particular BSS
10498 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10499 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10500 * As of now there is no possibility to get the mgmt(probe response)
10501 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10502 * and passing to cfg80211_inform_bss_frame.
10503 */
10504 struct net_device *dev = pAdapter->dev;
10505 struct wireless_dev *wdev = dev->ieee80211_ptr;
10506 struct wiphy *wiphy = wdev->wiphy;
10507 int chan_no = bss_desc->channelId;
10508#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10509 qcom_ie_age *qie_age = NULL;
10510 int ie_length =
10511 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10512#else
10513 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10514#endif
10515 const char *ie =
10516 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10517 unsigned int freq;
10518 struct ieee80211_channel *chan;
10519 struct ieee80211_mgmt *mgmt = NULL;
10520 struct cfg80211_bss *bss_status = NULL;
10521 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10522 int rssi = 0;
10523 hdd_context_t *pHddCtx;
10524 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010525 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010526 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010527
10528 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10529 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010530 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010531 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010532
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010533 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010534 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10535 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010536 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010537 return NULL;
10538 }
10539
10540 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10541
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010542 /* Android does not want the timestamp from the frame.
10543 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010544 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010545 mgmt->u.probe_resp.timestamp =
10546 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010547
10548 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10549 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10550
10551#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10552 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10553 /* Assuming this is the last IE, copy at the end */
10554 ie_length -= sizeof(qcom_ie_age);
10555 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10556 qie_age->element_id = QCOM_VENDOR_IE_ID;
10557 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10558 qie_age->oui_1 = QCOM_OUI1;
10559 qie_age->oui_2 = QCOM_OUI2;
10560 qie_age->oui_3 = QCOM_OUI3;
10561 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10562 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +053010563 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010565 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10566 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010567 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10568 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569#endif
10570
10571 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10572 if (bss_desc->fProbeRsp) {
10573 mgmt->frame_control |=
10574 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10575 } else {
10576 mgmt->frame_control |=
10577 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10578 }
10579
10580 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10581 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10582 freq =
10583 ieee80211_channel_to_frequency(chan_no,
10584 IEEE80211_BAND_2GHZ);
10585 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10586 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10587 freq =
10588 ieee80211_channel_to_frequency(chan_no,
10589 IEEE80211_BAND_5GHZ);
10590 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010591 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010592 kfree(mgmt);
10593 return NULL;
10594 }
10595
10596 chan = __ieee80211_get_channel(wiphy, freq);
10597 /* When the band is changed on the fly using the GUI, three things are done
10598 * 1. scan abort
10599 * 2. flush scan results from cache
10600 * 3. update the band with the new band user specified (refer to the
10601 * hdd_set_band_helper function) as part of the scan abort, message will be
10602 * queued to PE and we proceed with flushing and changinh the band.
10603 * PE will stop the scanning further and report back the results what ever
10604 * it had till now by calling the call back function.
10605 * if the time between update band and scandone call back is sufficient
10606 * enough the band change reflects in SME, SME validates the channels
10607 * and discards the channels correponding to previous band and calls back
10608 * with zero bss results. but if the time between band update and scan done
10609 * callback is very small then band change will not reflect in SME and SME
10610 * reports to HDD all the channels correponding to previous band.this is due
10611 * to race condition.but those channels are invalid to the new band and so
10612 * this function __ieee80211_get_channel will return NULL.Each time we
10613 * report scan result with this pointer null warning kernel trace is printed.
10614 * if the scan results contain large number of APs continuosly kernel
10615 * warning trace is printed and it will lead to apps watch dog bark.
10616 * So drop the bss and continue to next bss.
10617 */
10618 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010619 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10620 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010621 kfree(mgmt);
10622 return NULL;
10623 }
10624
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010625 /* Based on .ini configuration, raw rssi can be reported for bss.
10626 * Raw rssi is typically used for estimating power.
10627 */
10628
10629 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10630 bss_desc->rssi;
10631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010632 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010633 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010634
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010635 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010636 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010637 (int)(rssi / 100),
10638 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010639
10640 bss_status =
10641 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10642 GFP_KERNEL);
10643 kfree(mgmt);
10644 return bss_status;
10645}
10646
10647/**
10648 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10649 * @pAdapter: Pointer to adapter
10650 * @pRoamInfo: Pointer to roam info
10651 *
10652 * This function is used to update the BSS data base of CFG8011
10653 *
10654 * Return: struct cfg80211_bss pointer
10655 */
10656struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10657 tCsrRoamInfo *pRoamInfo)
10658{
10659 tCsrRoamConnectedProfile roamProfile;
10660 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10661 struct cfg80211_bss *bss = NULL;
10662
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10664 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10665
10666 if (NULL != roamProfile.pBssDesc) {
10667 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10668 roamProfile.pBssDesc);
10669
10670 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010671 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010672
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010673 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010674 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010675 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010676 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010677 return bss;
10678}
10679/**
10680 * wlan_hdd_cfg80211_update_bss() - update bss
10681 * @wiphy: Pointer to wiphy
10682 * @pAdapter: Pointer to adapter
10683 * @scan_time: scan request timestamp
10684 *
10685 * Return: zero if success, non-zero otherwise
10686 */
10687int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10688 hdd_adapter_t *pAdapter,
10689 uint32_t scan_time)
10690{
10691 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10692 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010693 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 tScanResultHandle pResult;
10695 struct cfg80211_bss *bss_status = NULL;
10696 hdd_context_t *pHddCtx;
10697 int ret;
10698
10699 ENTER();
10700
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010701 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010702 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10703 NO_SESSION, pAdapter->sessionId));
10704
10705 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10706 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010707 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010709
10710 /* start getting scan results and populate cgf80211 BSS database */
10711 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10712
10713 /* no scan results */
10714 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010715 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010716 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010717 }
10718
10719 pScanResult = sme_scan_result_get_first(hHal, pResult);
10720
10721 while (pScanResult) {
10722 /*
10723 * - cfg80211_inform_bss() is not updating ie field of bss
10724 * entry if entry already exists in bss data base of cfg80211
10725 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10726 * to update thebss entry instead of cfg80211_inform_bss,
10727 * But this call expects mgmt packet as input. As of now
10728 * there is no possibility to get the mgmt(probe response)
10729 * frame from PE, converting bss_desc to
10730 * ieee80211_mgmt(probe response) and passing to c
10731 * fg80211_inform_bss_frame.
10732 * - Update BSS only if beacon timestamp is later than
10733 * scan request timestamp.
10734 */
10735 if ((scan_time == 0) ||
10736 (scan_time <
10737 pScanResult->BssDescriptor.nReceivedTime)) {
10738 bss_status =
10739 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10740 &pScanResult->BssDescriptor);
10741
10742 if (NULL == bss_status) {
10743 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10744 } else {
10745 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010746 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747 bss_status);
10748 }
10749 } else {
10750 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10751 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10752 }
10753 pScanResult = sme_scan_result_get_next(hHal, pResult);
10754 }
10755
10756 sme_scan_result_purge(hHal, pResult);
10757 /*
10758 * For SAP mode, scan is invoked by hostapd during SAP start
10759 * if hostapd is restarted, we need to flush previous scan
10760 * result so that it will reflect environment change
10761 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010762 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10764 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10765#endif
10766 )
10767 sme_scan_flush_result(hHal);
10768
10769 EXIT();
10770 return 0;
10771}
10772
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773/**
10774 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10775 * @pAdapter: Pointer to adapter
10776 * @pRoamInfo: Pointer to roam info
10777 * @index: Index
10778 * @preauth: Preauth flag
10779 *
10780 * This function is used to notify the supplicant of a new PMKSA candidate.
10781 *
10782 * Return: 0 for success, non-zero for failure
10783 */
10784int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10785 tCsrRoamInfo *pRoamInfo,
10786 int index, bool preauth)
10787{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 struct net_device *dev = pAdapter->dev;
10789 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10790
10791 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010792 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793
10794 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010795 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796 return -EINVAL;
10797 }
10798
10799 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010800 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10802 cfg80211_pmksa_candidate_notify(dev, index,
10803 pRoamInfo->bssid.bytes,
10804 preauth, GFP_KERNEL);
10805 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 return 0;
10807}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808
10809#ifdef FEATURE_WLAN_LFR_METRICS
10810/**
10811 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10812 * @pAdapter: Pointer to adapter
10813 * @pRoamInfo: Pointer to roam info
10814 *
10815 * 802.11r/LFR metrics reporting function to report preauth initiation
10816 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010817 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818 */
10819#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010820QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010821 tCsrRoamInfo *pRoamInfo)
10822{
10823 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10824 union iwreq_data wrqu;
10825
10826 ENTER();
10827
10828 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010829 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010830 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 }
10832
10833 /* create the event */
10834 memset(&wrqu, 0, sizeof(wrqu));
10835 memset(metrics_notification, 0, sizeof(metrics_notification));
10836
10837 wrqu.data.pointer = metrics_notification;
10838 wrqu.data.length = scnprintf(metrics_notification,
10839 sizeof(metrics_notification),
10840 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10841 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10842
10843 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10844 metrics_notification);
10845
10846 EXIT();
10847
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010848 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849}
10850
10851/**
10852 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10853 * @pAdapter: Pointer to adapter
10854 * @pRoamInfo: Pointer to roam info
10855 * @preauth_status: Preauth status
10856 *
10857 * 802.11r/LFR metrics reporting function to report handover initiation
10858 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010859 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010860 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010861QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10863 tCsrRoamInfo *pRoamInfo,
10864 bool preauth_status)
10865{
10866 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10867 union iwreq_data wrqu;
10868
10869 ENTER();
10870
10871 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010872 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010873 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874 }
10875
10876 /* create the event */
10877 memset(&wrqu, 0, sizeof(wrqu));
10878 memset(metrics_notification, 0, sizeof(metrics_notification));
10879
10880 scnprintf(metrics_notification, sizeof(metrics_notification),
10881 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10882 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10883
10884 if (1 == preauth_status)
10885 strlcat(metrics_notification, " true",
10886 sizeof(metrics_notification));
10887 else
10888 strlcat(metrics_notification, " false",
10889 sizeof(metrics_notification));
10890
10891 wrqu.data.pointer = metrics_notification;
10892 wrqu.data.length = strlen(metrics_notification);
10893
10894 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10895 metrics_notification);
10896
10897 EXIT();
10898
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010899 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900}
10901
10902/**
10903 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10904 * @pAdapter: Pointer to adapter
10905 * @pRoamInfo: Pointer to roam info
10906 *
10907 * 802.11r/LFR metrics reporting function to report handover initiation
10908 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010909 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010911QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912 tCsrRoamInfo *pRoamInfo)
10913{
10914 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10915 union iwreq_data wrqu;
10916
10917 ENTER();
10918
10919 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010920 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010921 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010922 }
10923
10924 /* create the event */
10925 memset(&wrqu, 0, sizeof(wrqu));
10926 memset(metrics_notification, 0, sizeof(metrics_notification));
10927
10928 wrqu.data.pointer = metrics_notification;
10929 wrqu.data.length = scnprintf(metrics_notification,
10930 sizeof(metrics_notification),
10931 "QCOM: LFR_PREAUTH_HANDOVER "
10932 MAC_ADDRESS_STR,
10933 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10934
10935 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10936 metrics_notification);
10937
10938 EXIT();
10939
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010940 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941}
10942#endif
10943
10944/**
10945 * hdd_select_cbmode() - select channel bonding mode
10946 * @pAdapter: Pointer to adapter
10947 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010948 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010949 *
10950 * Return: none
10951 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010952void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10953 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010954{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010955 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010956 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010957 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010958
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010959 /*
10960 * CDS api expects secondary channel for calculating
10961 * the channel params
10962 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010963 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010964 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
10965 if (operationChannel >= 1 && operationChannel <= 5)
10966 sec_ch = operationChannel + 4;
10967 else if (operationChannel >= 6 && operationChannel <= 13)
10968 sec_ch = operationChannel - 4;
10969 }
10970
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010972 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010973
10974 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010975 eHddDot11Mode hdd_dot11_mode;
10976 uint8_t iniDot11Mode =
10977 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
10978
10979 hdd_notice("Dot11Mode is %u", iniDot11Mode);
10980 switch (iniDot11Mode) {
10981 case eHDD_DOT11_MODE_AUTO:
10982 case eHDD_DOT11_MODE_11ac:
10983 case eHDD_DOT11_MODE_11ac_ONLY:
10984 if (sme_is_feature_supported_by_fw(DOT11AC))
10985 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
10986 else
10987 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10988 break;
10989 case eHDD_DOT11_MODE_11n:
10990 case eHDD_DOT11_MODE_11n_ONLY:
10991 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10992 break;
10993 default:
10994 hdd_dot11_mode = iniDot11Mode;
10995 break;
10996 }
10997 ch_info->channel_width = ch_params->ch_width;
10998 ch_info->phy_mode =
10999 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011000 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011001 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011002 hdd_info("ch_info width %d, phymode %d channel %d",
11003 ch_info->channel_width, ch_info->phy_mode,
11004 ch_info->channel);
11005 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006}
11007
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011008/**
11009 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11010 * @adapter: STA adapter
11011 * @roam_profile: STA roam profile
11012 *
11013 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11014 *
11015 * Return: false if sta-sap conc is not allowed, else return true
11016 */
11017static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11018 tCsrRoamProfile *roam_profile)
11019{
11020 hdd_context_t *hdd_ctx;
11021 hdd_adapter_t *ap_adapter;
11022 hdd_ap_ctx_t *hdd_ap_ctx;
11023 hdd_hostapd_state_t *hostapd_state;
11024 uint8_t channel = 0;
11025 QDF_STATUS status;
11026
11027 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11028 if (!hdd_ctx) {
11029 hdd_err("HDD context is NULL");
11030 return true;
11031 }
11032
11033 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11034 /* probably no sap running, no handling required */
11035 if (ap_adapter == NULL)
11036 return true;
11037
11038 /*
11039 * sap is not in started state, so it is fine to go ahead with sta.
11040 * if sap is currently doing CAC then don't allow sta to go further.
11041 */
11042 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11043 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11044 return true;
11045
11046 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11047 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11048 return false;
11049 }
11050
11051 /*
11052 * log and return error, if we allow STA to go through, we don't
11053 * know what is going to happen better stop sta connection
11054 */
11055 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11056 if (NULL == hdd_ap_ctx) {
11057 hdd_err("AP context not found");
11058 return false;
11059 }
11060
11061 /* sap is on non-dfs channel, nothing to handle */
11062 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11063 hdd_info("sap is on non-dfs channel, sta is allowed");
11064 return true;
11065 }
11066 /*
11067 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011068 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011069 */
11070 status = cds_get_channel_from_scan_result(adapter,
11071 roam_profile, &channel);
11072
Nitesh Shah59774522016-09-16 15:14:21 +053011073 /*
11074 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11075 * channels for roaming case.
11076 */
11077 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11078 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11079 return true;
11080 }
11081
11082 /*
11083 * If channel is 0 or DFS then better to call pcl and find out the
11084 * best channel. If channel is non-dfs 5 GHz then better move SAP
11085 * to STA's channel to make scc, so we have room for 3port MCC
11086 * scenario.
11087 */
11088 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011089 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11090 true);
11091
11092 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11093 qdf_event_reset(&hostapd_state->qdf_event);
11094 status = wlansap_set_channel_change_with_csa(
11095 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11096 hdd_ap_ctx->sapConfig.ch_width_orig);
11097
11098 if (QDF_STATUS_SUCCESS != status) {
11099 hdd_err("Set channel with CSA IE failed, can't allow STA");
11100 return false;
11101 }
11102
11103 /*
11104 * wait here for SAP to finish the channel switch. When channel
11105 * switch happens, SAP sends few beacons with CSA_IE. After
11106 * successfully Transmission of those beacons, it will move its
11107 * state from started to disconnected and move to new channel.
11108 * once it moves to new channel, sap again moves its state
11109 * machine from disconnected to started and set this event.
11110 * wait for 10 secs to finish this.
11111 */
11112 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11113 if (!QDF_IS_STATUS_SUCCESS(status)) {
11114 hdd_err("wait for qdf_event failed, STA not allowed!!");
11115 return false;
11116 }
11117
11118 return true;
11119}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011120
Krunal Soni31949422016-07-29 17:17:53 -070011121/**
11122 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011124 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011125 * @ssid_len: Length of ssid
11126 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011127 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011129 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011130 *
11131 * This function is used to start the association process
11132 *
11133 * Return: 0 for success, non-zero for failure
11134 */
Krunal Soni31949422016-07-29 17:17:53 -070011135static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011136 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011137 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011138 u8 operatingChannel,
11139 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011140{
11141 int status = 0;
11142 hdd_wext_state_t *pWextState;
11143 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011144 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 uint32_t roamId;
11146 tCsrRoamProfile *pRoamProfile;
11147 eCsrAuthType RSNAuthType;
11148 tSmeConfigParams *sme_config;
11149
11150 ENTER();
11151
11152 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11153 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011154 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011155
11156 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011157 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159
11160 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011161 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011162 return -EINVAL;
11163 }
11164
11165 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011166 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11167 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168
11169 if (pRoamProfile) {
11170 hdd_station_ctx_t *pHddStaCtx;
11171 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11172
11173 if (HDD_WMM_USER_MODE_NO_QOS ==
11174 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11175 /*QoS not enabled in cfg file */
11176 pRoamProfile->uapsd_mask = 0;
11177 } else {
11178 /*QoS enabled, update uapsd mask from cfg file */
11179 pRoamProfile->uapsd_mask =
11180 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11181 }
11182
11183 pRoamProfile->SSIDs.numOfSSIDs = 1;
11184 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011185 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011187 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011188 ssid, ssid_len);
11189
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011190 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011191 if (bssid) {
11192 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011193 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011194 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011195 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011196 /*
11197 * Save BSSID in seperate variable as
11198 * pRoamProfile's BSSID is getting zeroed out in the
11199 * association process. In case of join failure
11200 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011202 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011203 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011204 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 } else if (bssid_hint) {
11206 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011207 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011208 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011209 /*
11210 * Save BSSID in a separate variable as
11211 * pRoamProfile's BSSID is getting zeroed out in the
11212 * association process. In case of join failure
11213 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011214 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011215 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011216 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011217 hdd_info("bssid_hint is given by upper layer %pM",
11218 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011220 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011221 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011222 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223 }
11224
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011225 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 pRoamProfile->SSIDs.SSIDList->SSID.length,
11227 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11228 operatingChannel);
11229
11230 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11231 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11234 }
11235#ifdef FEATURE_WLAN_WAPI
11236 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011237 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 switch (pAdapter->wapi_info.wapiAuthMode) {
11239 case WAPI_AUTH_MODE_PSK:
11240 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011241 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 pAdapter->wapi_info.wapiAuthMode);
11243 pRoamProfile->AuthType.authType[0] =
11244 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11245 break;
11246 }
11247 case WAPI_AUTH_MODE_CERT:
11248 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011249 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 pAdapter->wapi_info.wapiAuthMode);
11251 pRoamProfile->AuthType.authType[0] =
11252 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11253 break;
11254 }
11255 } /* End of switch */
11256 if (pAdapter->wapi_info.wapiAuthMode ==
11257 WAPI_AUTH_MODE_PSK
11258 || pAdapter->wapi_info.wapiAuthMode ==
11259 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011260 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011261 pRoamProfile->AuthType.numEntries = 1;
11262 pRoamProfile->EncryptionType.numEntries = 1;
11263 pRoamProfile->EncryptionType.encryptionType[0] =
11264 eCSR_ENCRYPT_TYPE_WPI;
11265 pRoamProfile->mcEncryptionType.numEntries = 1;
11266 pRoamProfile->mcEncryptionType.
11267 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11268 }
11269 }
Krunal Soni31949422016-07-29 17:17:53 -070011270#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011271#ifdef WLAN_FEATURE_GTK_OFFLOAD
11272 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011273 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11274 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11276 sizeof(tSirGtkOffloadParams));
11277 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11278 GTK_OFFLOAD_DISABLE;
11279 }
11280#endif
11281 pRoamProfile->csrPersona = pAdapter->device_mode;
11282
11283 if (operatingChannel) {
11284 pRoamProfile->ChannelInfo.ChannelList =
11285 &operatingChannel;
11286 pRoamProfile->ChannelInfo.numOfChannels = 1;
11287 } else {
11288 pRoamProfile->ChannelInfo.ChannelList = NULL;
11289 pRoamProfile->ChannelInfo.numOfChannels = 0;
11290 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011291 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011292 && operatingChannel) {
11293 /*
11294 * Need to post the IBSS power save parameters
11295 * to WMA. WMA will configure this parameters
11296 * to firmware if power save is enabled by the
11297 * firmware.
11298 */
11299 status = hdd_set_ibss_power_save_params(pAdapter);
11300
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011301 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011302 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011303 return -EINVAL;
11304 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011305 pRoamProfile->ch_params.ch_width =
11306 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011307 /*
11308 * In IBSS mode while operating in 2.4 GHz,
11309 * the device supports only 20 MHz.
11310 */
11311 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11312 pRoamProfile->ch_params.ch_width =
11313 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011314 hdd_select_cbmode(pAdapter, operatingChannel,
11315 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011316 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011317 /*
11318 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11319 * or pmf=2 is an explicit configuration in the supplicant
11320 * configuration, drop the connection request.
11321 */
11322 if (pWextState->roamProfile.MFPEnabled &&
11323 !(pWextState->roamProfile.MFPRequired ||
11324 pWextState->roamProfile.MFPCapable)) {
11325 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11326 pWextState->roamProfile.MFPEnabled,
11327 pWextState->roamProfile.MFPRequired,
11328 pWextState->roamProfile.MFPCapable);
11329 return -EINVAL;
11330 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331
Krunal Soni3091bcc2016-06-23 12:28:21 -070011332 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 hdd_err("Connection refused: conn in progress");
11334 return -EINVAL;
11335 }
11336
Krunal Soni31949422016-07-29 17:17:53 -070011337 /*
11338 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011340 * enhancements, the supplicant is not issuing the scan command
11341 * now. So the unicast frames which are sent from the host are
11342 * not having the additional IEs. If it is P2P CLIENT and there
11343 * is no additional IE present in roamProfile, then use the
11344 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011345 */
11346
Krunal Sonib4326f22016-03-10 13:05:51 -080011347 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348 (!pRoamProfile->pAddIEScan)) {
11349 pRoamProfile->pAddIEScan =
11350 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11351 pRoamProfile->nAddIEScanLength =
11352 pAdapter->scan_info.scanAddIE.length;
11353 }
11354 /*
11355 * When policy manager is enabled from ini file, we shouldn't
11356 * check for other concurrency rules.
11357 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011358 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011359 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011360 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361 pAdapter, pRoamProfile, &roamId))
11362 return 0;
11363 }
11364
Krunal Soni3091bcc2016-06-23 12:28:21 -070011365 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011366 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11367 pRoamProfile))) {
11368 hdd_err("sap-sta conc will fail, can't allow sta");
11369 hdd_conn_set_connection_state(pAdapter,
11370 eConnectionState_NotConnected);
11371 return -ENOMEM;
11372 }
11373
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011374 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375 if (!sme_config) {
11376 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011377 hdd_conn_set_connection_state(pAdapter,
11378 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011379 return -ENOMEM;
11380 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011381 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 sme_get_config_param(pHddCtx->hHal, sme_config);
11383 /* These values are not sessionized. So, any change in these SME
11384 * configs on an older or parallel interface will affect the
11385 * cb mode. So, restoring the default INI params before starting
11386 * interfaces such as sta, cli etc.,
11387 */
11388 sme_config->csrConfig.channelBondingMode5GHz =
11389 pHddCtx->config->nChannelBondingMode5GHz;
11390 sme_config->csrConfig.channelBondingMode24GHz =
11391 pHddCtx->config->nChannelBondingMode24GHz;
11392 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011393 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011394 /*
11395 * Change conn_state to connecting before sme_roam_connect(),
11396 * because sme_roam_connect() has a direct path to call
11397 * hdd_sme_roam_callback(), which will change the conn_state
11398 * If direct path, conn_state will be accordingly changed to
11399 * NotConnected or Associated by either
11400 * hdd_association_completion_handler() or
11401 * hdd_dis_connect_handler() in sme_RoamCallback()if
11402 * sme_RomConnect is to be queued,
11403 * Connecting state will remain until it is completed.
11404 *
11405 * If connection state is not changed, connection state will
11406 * remain in eConnectionState_NotConnected state.
11407 * In hdd_association_completion_handler, "hddDisconInProgress"
11408 * is set to true if conn state is
11409 * eConnectionState_NotConnected.
11410 * If "hddDisconInProgress" is set to true then cfg80211 layer
11411 * is not informed of connect result indication which
11412 * is an issue.
11413 */
11414 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011415 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011416 hdd_conn_set_connection_state(pAdapter,
11417 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011418
11419 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11420 pAdapter->sessionId, pRoamProfile,
11421 &roamId);
11422
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011423 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011424 (QDF_STA_MODE == pAdapter->device_mode ||
11425 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011426 hdd_err("sme_roam_connect (session %d) failed with "
11427 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 pAdapter->sessionId, status);
11429 /* change back to NotAssociated */
11430 hdd_conn_set_connection_state(pAdapter,
11431 eConnectionState_NotConnected);
11432 }
11433
11434 pRoamProfile->ChannelInfo.ChannelList = NULL;
11435 pRoamProfile->ChannelInfo.numOfChannels = 0;
11436
11437 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011438 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011439 return -EINVAL;
11440 }
11441 EXIT();
11442 return status;
11443}
11444
11445/**
11446 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11447 * @pAdapter: Pointer to adapter
11448 * @auth_type: Auth type
11449 *
11450 * This function is used to set the authentication type (OPEN/SHARED).
11451 *
11452 * Return: 0 for success, non-zero for failure
11453 */
11454static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11455 enum nl80211_auth_type auth_type)
11456{
11457 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11458 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011460 /*set authentication type */
11461 switch (auth_type) {
11462 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011463 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11465 break;
11466
11467 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011469 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11471 break;
11472
11473 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011474 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11476 break;
11477#ifdef FEATURE_WLAN_ESE
11478 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011479 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11481 break;
11482#endif
11483
11484 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011485 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011486 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11487 return -EINVAL;
11488 }
11489
11490 pWextState->roamProfile.AuthType.authType[0] =
11491 pHddStaCtx->conn_info.authType;
11492 return 0;
11493}
11494
11495/**
11496 * wlan_hdd_set_akm_suite() - set key management type
11497 * @pAdapter: Pointer to adapter
11498 * @key_mgmt: Key management type
11499 *
11500 * This function is used to set the key mgmt type(PSK/8021x).
11501 *
11502 * Return: 0 for success, non-zero for failure
11503 */
11504static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11505{
11506 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11509#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11510 /*set key mgmt type */
11511 switch (key_mgmt) {
11512 case WLAN_AKM_SUITE_PSK:
11513 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011515 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11517 break;
11518
11519 case WLAN_AKM_SUITE_8021X_SHA256:
11520 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011521 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011522 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11524 break;
11525#ifdef FEATURE_WLAN_ESE
11526#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11527#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11528 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011529 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011530 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11531 break;
11532#endif
11533#ifndef WLAN_AKM_SUITE_OSEN
11534#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11535#endif
11536 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011537 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11539 break;
11540
11541 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011542 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 return -EINVAL;
11544
11545 }
11546 return 0;
11547}
11548
11549/**
11550 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11551 * @pAdapter: Pointer to adapter
11552 * @cipher: Cipher type
11553 * @ucast: Unicast flag
11554 *
11555 * This function is used to set the encryption type
11556 * (NONE/WEP40/WEP104/TKIP/CCMP).
11557 *
11558 * Return: 0 for success, non-zero for failure
11559 */
11560static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11561 u32 cipher, bool ucast)
11562{
11563 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11564 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11565 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11566
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011568 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11570 } else {
11571
11572 /*set encryption method */
11573 switch (cipher) {
11574 case IW_AUTH_CIPHER_NONE:
11575 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11576 break;
11577
11578 case WLAN_CIPHER_SUITE_WEP40:
11579 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11580 break;
11581
11582 case WLAN_CIPHER_SUITE_WEP104:
11583 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11584 break;
11585
11586 case WLAN_CIPHER_SUITE_TKIP:
11587 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11588 break;
11589
11590 case WLAN_CIPHER_SUITE_CCMP:
11591 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11592 break;
11593#ifdef FEATURE_WLAN_WAPI
11594 case WLAN_CIPHER_SUITE_SMS4:
11595 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11596 break;
11597#endif
11598
11599#ifdef FEATURE_WLAN_ESE
11600 case WLAN_CIPHER_SUITE_KRK:
11601 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11602 break;
11603#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11604 case WLAN_CIPHER_SUITE_BTK:
11605 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11606 break;
11607#endif
11608#endif
11609 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011610 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611 return -EOPNOTSUPP;
11612 }
11613 }
11614
11615 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011616 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011617 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11618 pWextState->roamProfile.EncryptionType.numEntries = 1;
11619 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11620 encryptionType;
11621 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011622 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11624 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11625 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11626 encryptionType;
11627 }
11628
11629 return 0;
11630}
11631
11632/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011633 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11634 * @wext_state: Pointer to wext state
11635 * @gen_ie: Pointer to IE data
11636 * @len: length of IE data
11637 *
11638 * Return: 0 for success, non-zero for failure
11639 */
11640static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11641 const uint8_t *gen_ie, uint16_t len)
11642{
11643 uint16_t cur_add_ie_len =
11644 wext_state->assocAddIE.length;
11645
11646 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11647 (wext_state->assocAddIE.length + len)) {
11648 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11649 QDF_ASSERT(0);
11650 return -ENOMEM;
11651 }
11652 memcpy(wext_state->assocAddIE.addIEdata +
11653 cur_add_ie_len, gen_ie, len);
11654 wext_state->assocAddIE.length += len;
11655
11656 wext_state->roamProfile.pAddIEAssoc =
11657 wext_state->assocAddIE.addIEdata;
11658 wext_state->roamProfile.nAddIEAssocLength =
11659 wext_state->assocAddIE.length;
11660 return 0;
11661}
11662
11663/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 * wlan_hdd_cfg80211_set_ie() - set IEs
11665 * @pAdapter: Pointer to adapter
11666 * @ie: Pointer ot ie
11667 * @ie: IE length
11668 *
11669 * Return: 0 for success, non-zero for failure
11670 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011671static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011672 size_t ie_len)
11673{
11674 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11675 const uint8_t *genie = ie;
11676 uint16_t remLen = ie_len;
11677#ifdef FEATURE_WLAN_WAPI
11678 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11679 u16 *tmp;
11680 uint16_t akmsuiteCount;
11681 int *akmlist;
11682#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011683 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011684
11685 /* clear previous assocAddIE */
11686 pWextState->assocAddIE.length = 0;
11687 pWextState->roamProfile.bWPSAssociation = false;
11688 pWextState->roamProfile.bOSENAssociation = false;
11689
11690 while (remLen >= 2) {
11691 uint16_t eLen = 0;
11692 uint8_t elementId;
11693 elementId = *genie++;
11694 eLen = *genie++;
11695 remLen -= 2;
11696
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011697 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698
11699 switch (elementId) {
11700 case DOT11F_EID_WPA:
11701 if (4 > eLen) { /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011702 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011703 return -EINVAL;
11704 } else if (0 ==
11705 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11706 uint16_t curAddIELen =
11707 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011708 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709
11710 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11711 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011712 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011713 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714 return -ENOMEM;
11715 }
11716 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11717 memcpy(pWextState->assocAddIE.addIEdata +
11718 curAddIELen, genie - 2, eLen + 2);
11719 pWextState->assocAddIE.length += eLen + 2;
11720
11721 pWextState->roamProfile.bWPSAssociation = true;
11722 pWextState->roamProfile.pAddIEAssoc =
11723 pWextState->assocAddIE.addIEdata;
11724 pWextState->roamProfile.nAddIEAssocLength =
11725 pWextState->assocAddIE.length;
11726 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011727 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011728 memset(pWextState->WPARSNIE, 0,
11729 MAX_WPA_RSN_IE_LEN);
11730 memcpy(pWextState->WPARSNIE, genie - 2,
11731 (eLen + 2));
11732 pWextState->roamProfile.pWPAReqIE =
11733 pWextState->WPARSNIE;
11734 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11735 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11736 P2P_OUI_TYPE_SIZE))) {
11737 uint16_t curAddIELen =
11738 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011739 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740
11741 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11742 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011743 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011744 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011745 return -ENOMEM;
11746 }
11747 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11748 memcpy(pWextState->assocAddIE.addIEdata +
11749 curAddIELen, genie - 2, eLen + 2);
11750 pWextState->assocAddIE.length += eLen + 2;
11751
11752 pWextState->roamProfile.pAddIEAssoc =
11753 pWextState->assocAddIE.addIEdata;
11754 pWextState->roamProfile.nAddIEAssocLength =
11755 pWextState->assocAddIE.length;
11756 }
11757#ifdef WLAN_FEATURE_WFD
11758 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11759 WFD_OUI_TYPE_SIZE)) &&
11760 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011761 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011762 pAdapter->device_mode)) {
11763 uint16_t curAddIELen =
11764 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011765 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766
11767 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11768 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011769 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011770 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 return -ENOMEM;
11772 }
11773 /* WFD IE is saved to Additional IE ; it should
11774 * be accumulated to handle WPS IE + P2P IE +
11775 * WFD IE */
11776 memcpy(pWextState->assocAddIE.addIEdata +
11777 curAddIELen, genie - 2, eLen + 2);
11778 pWextState->assocAddIE.length += eLen + 2;
11779
11780 pWextState->roamProfile.pAddIEAssoc =
11781 pWextState->assocAddIE.addIEdata;
11782 pWextState->roamProfile.nAddIEAssocLength =
11783 pWextState->assocAddIE.length;
11784 }
11785#endif
11786 /* Appending HS 2.0 Indication Element in Assiciation Request */
11787 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11788 HS20_OUI_TYPE_SIZE))) {
11789 uint16_t curAddIELen =
11790 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011791 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011792
11793 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11794 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011795 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011796 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 return -ENOMEM;
11798 }
11799 memcpy(pWextState->assocAddIE.addIEdata +
11800 curAddIELen, genie - 2, eLen + 2);
11801 pWextState->assocAddIE.length += eLen + 2;
11802
11803 pWextState->roamProfile.pAddIEAssoc =
11804 pWextState->assocAddIE.addIEdata;
11805 pWextState->roamProfile.nAddIEAssocLength =
11806 pWextState->assocAddIE.length;
11807 }
11808 /* Appending OSEN Information Element in Assiciation Request */
11809 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11810 OSEN_OUI_TYPE_SIZE))) {
11811 uint16_t curAddIELen =
11812 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011813 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011814
11815 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11816 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011817 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011818 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011819 return -ENOMEM;
11820 }
11821 memcpy(pWextState->assocAddIE.addIEdata +
11822 curAddIELen, genie - 2, eLen + 2);
11823 pWextState->assocAddIE.length += eLen + 2;
11824
11825 pWextState->roamProfile.bOSENAssociation = true;
11826 pWextState->roamProfile.pAddIEAssoc =
11827 pWextState->assocAddIE.addIEdata;
11828 pWextState->roamProfile.nAddIEAssocLength =
11829 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011830 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11831 MBO_OUI_TYPE_SIZE))){
11832 hdd_info("Set MBO IE(len %d)", eLen + 2);
11833 status = wlan_hdd_add_assoc_ie(pWextState,
11834 genie - 2, eLen + 2);
11835 if (status)
11836 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 } else {
11838 uint16_t add_ie_len =
11839 pWextState->assocAddIE.length;
11840
11841 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11842
11843 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11844 (pWextState->assocAddIE.length + eLen)) {
11845 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011846 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011847 return -ENOMEM;
11848 }
11849
11850 memcpy(pWextState->assocAddIE.addIEdata +
11851 add_ie_len, genie - 2, eLen + 2);
11852 pWextState->assocAddIE.length += eLen + 2;
11853
11854 pWextState->roamProfile.pAddIEAssoc =
11855 pWextState->assocAddIE.addIEdata;
11856 pWextState->roamProfile.nAddIEAssocLength =
11857 pWextState->assocAddIE.length;
11858 }
11859 break;
11860 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011861 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011862 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11863 memcpy(pWextState->WPARSNIE, genie - 2,
11864 (eLen + 2));
11865 pWextState->roamProfile.pRSNReqIE =
11866 pWextState->WPARSNIE;
11867 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11868 break;
11869 /*
11870 * Appending Extended Capabilities with Interworking bit set
11871 * in Assoc Req.
11872 *
11873 * In assoc req this EXT Cap will only be taken into account if
11874 * interworkingService bit is set to 1. Currently
11875 * driver is only interested in interworkingService capability
11876 * from supplicant. If in future any other EXT Cap info is
11877 * required from supplicat, it needs to be handled while
11878 * sending Assoc Req in LIM.
11879 */
11880 case DOT11F_EID_EXTCAP:
11881 {
11882 uint16_t curAddIELen =
11883 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011884 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885
11886 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11887 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011888 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011889 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890 return -ENOMEM;
11891 }
11892 memcpy(pWextState->assocAddIE.addIEdata +
11893 curAddIELen, genie - 2, eLen + 2);
11894 pWextState->assocAddIE.length += eLen + 2;
11895
11896 pWextState->roamProfile.pAddIEAssoc =
11897 pWextState->assocAddIE.addIEdata;
11898 pWextState->roamProfile.nAddIEAssocLength =
11899 pWextState->assocAddIE.length;
11900 break;
11901 }
11902#ifdef FEATURE_WLAN_WAPI
11903 case WLAN_EID_WAPI:
11904 /* Setting WAPI Mode to ON=1 */
11905 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011906 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011907 tmp = (u16 *) ie;
11908 tmp = tmp + 2; /* Skip element Id and Len, Version */
11909 akmsuiteCount = WPA_GET_LE16(tmp);
11910 tmp = tmp + 1;
11911 akmlist = (int *)(tmp);
11912 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11913 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11914 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011915 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011916 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011917 return -EINVAL;
11918 }
11919
11920 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011921 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011922 pAdapter->wapi_info.wapiAuthMode =
11923 WAPI_AUTH_MODE_PSK;
11924 }
11925 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011926 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927 pAdapter->wapi_info.wapiAuthMode =
11928 WAPI_AUTH_MODE_CERT;
11929 }
11930 break;
11931#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011932 case DOT11F_EID_SUPPOPERATINGCLASSES:
11933 {
11934 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11935 status = wlan_hdd_add_assoc_ie(pWextState,
11936 genie - 2, eLen + 2);
11937 if (status)
11938 return status;
11939 break;
11940 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011942 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011943 /* when Unknown IE is received we should break and continue
11944 * to the next IE in the buffer instead we were returning
11945 * so changing this to break */
11946 break;
11947 }
11948 genie += eLen;
11949 remLen -= eLen;
11950 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011951 return 0;
11952}
11953
11954/**
11955 * hdd_is_wpaie_present() - check for WPA ie
11956 * @ie: Pointer to ie
11957 * @ie_len: Ie length
11958 *
11959 * Parse the received IE to find the WPA IE
11960 *
11961 * Return: true if wpa ie is found else false
11962 */
11963static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
11964{
11965 uint8_t eLen = 0;
11966 uint16_t remLen = ie_len;
11967 uint8_t elementId = 0;
11968
11969 while (remLen >= 2) {
11970 elementId = *ie++;
11971 eLen = *ie++;
11972 remLen -= 2;
11973 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011974 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975 return false;
11976 }
11977 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
11978 /* OUI - 0x00 0X50 0XF2
11979 * WPA Information Element - 0x01
11980 * WPA version - 0x01
11981 */
11982 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
11983 return true;
11984 }
11985 ie += eLen;
11986 remLen -= eLen;
11987 }
11988 return false;
11989}
11990
11991/**
11992 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
11993 * @pAdapter: Pointer to adapter
11994 * @req: Pointer to security parameters
11995 *
11996 * Return: 0 for success, non-zero for failure
11997 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011998static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
11999 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012000{
12001 int status = 0;
12002 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12003 ENTER();
12004
12005 /*set wpa version */
12006 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12007
12008 if (req->crypto.wpa_versions) {
12009 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12010 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12011 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12012 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12013 }
12014 }
12015
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012016 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012017
12018 /*set authentication type */
12019 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12020
12021 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012022 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012023 return status;
12024 }
12025
12026 /*set key mgmt type */
12027 if (req->crypto.n_akm_suites) {
12028 status =
12029 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12030 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012031 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012032 return status;
12033 }
12034 }
12035
12036 /*set pairwise cipher type */
12037 if (req->crypto.n_ciphers_pairwise) {
12038 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12039 req->crypto.
12040 ciphers_pairwise[0],
12041 true);
12042 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012043 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012044 return status;
12045 }
12046 } else {
12047 /*Reset previous cipher suite to none */
12048 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12049 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012050 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012051 return status;
12052 }
12053 }
12054
12055 /*set group cipher type */
12056 status =
12057 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12058 false);
12059
12060 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012061 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 return status;
12063 }
12064#ifdef WLAN_FEATURE_11W
12065 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12066#endif
12067
12068 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12069 if (req->ie_len) {
12070 status =
12071 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12072 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012073 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012074 return status;
12075 }
12076 }
12077
12078 /*incase of WEP set default key information */
12079 if (req->key && req->key_len) {
12080 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12081 || (WLAN_CIPHER_SUITE_WEP104 ==
12082 req->crypto.ciphers_pairwise[0])
12083 ) {
12084 if (IW_AUTH_KEY_MGMT_802_1X
12085 ==
12086 (pWextState->
12087 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012088 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012089 return -EOPNOTSUPP;
12090 } else {
12091 u8 key_len = req->key_len;
12092 u8 key_idx = req->key_idx;
12093
12094 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12095 key_len)
12096 && (CSR_MAX_NUM_KEY > key_idx)
12097 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012098 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012099 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012100 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012101 Keys.
12102 KeyMaterial[key_idx][0],
12103 req->key, key_len);
12104 pWextState->roamProfile.Keys.
12105 KeyLength[key_idx] = (u8) key_len;
12106 pWextState->roamProfile.Keys.
12107 defaultIndex = (u8) key_idx;
12108 }
12109 }
12110 }
12111 }
12112
12113 return status;
12114}
12115
12116/**
12117 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12118 * @pAdapter: Pointer to adapter
12119 *
12120 * This function is used to disconnect from previous connection
12121 *
12122 * Return: 0 for success, non-zero for failure
12123 */
12124static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12125{
12126 unsigned long rc;
12127 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012128 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129
12130 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12131
Jeff Johnson9edf9572016-10-03 15:24:49 -070012132 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012133 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12134 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12135 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 hdd_conn_set_connection_state(pAdapter,
12137 eConnectionState_Disconnecting);
12138 /* Issue disconnect to CSR */
12139 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012140
12141 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12142 pAdapter->sessionId,
12143 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12144 /*
12145 * Wait here instead of returning directly, this will block the
12146 * next connect command and allow processing of the scan for
12147 * ssid and the previous connect command in CSR. Else we might
12148 * hit some race conditions leading to SME and HDD out of sync.
12149 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012150 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012151 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12152 } else if (0 != status) {
12153 hdd_err("csrRoamDisconnect failure, returned %d",
12154 (int)status);
12155 pHddStaCtx->staDebugState = status;
12156 result = -EINVAL;
12157 goto disconnected;
12158 }
12159
12160 rc = wait_for_completion_timeout(
12161 &pAdapter->disconnect_comp_var,
12162 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012163 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012164 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12165 pAdapter->sessionId, pHddStaCtx->staDebugState);
12166 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167 }
12168 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012169 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012171 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012172 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012173 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012175 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176 }
12177 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012178disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012179 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12180 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181}
12182
12183/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012184 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12185 * @adapter: Pointer to the HDD adapter
12186 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012187 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012188 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012189 * This function will start reassociation if prev_bssid is set and bssid/
12190 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012191 *
Naveen Rawat07332902016-07-27 09:13:17 -070012192 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012193 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012194#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12195 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012196static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12197 struct cfg80211_connect_params *req,
12198 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012199{
Naveen Rawat07332902016-07-27 09:13:17 -070012200 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012201 const uint8_t *bssid = NULL;
12202 uint16_t channel = 0;
12203
12204 if (req->bssid)
12205 bssid = req->bssid;
12206 else if (req->bssid_hint)
12207 bssid = req->bssid_hint;
12208
12209 if (req->channel)
12210 channel = req->channel->hw_value;
12211 else if (req->channel_hint)
12212 channel = req->channel_hint->hw_value;
12213
12214 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012215 reassoc = true;
12216 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012217 channel, MAC_ADDR_ARRAY(bssid));
12218 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012219 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012220 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012221 }
Naveen Rawat07332902016-07-27 09:13:17 -070012222 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012223}
12224#else
Naveen Rawat07332902016-07-27 09:13:17 -070012225static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12226 struct cfg80211_connect_params *req,
12227 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012228{
Naveen Rawat07332902016-07-27 09:13:17 -070012229 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012230}
12231#endif
12232
12233/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012234 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12235 * @wiphy: Pointer to wiphy
12236 * @dev: Pointer to network device
12237 * @req: Pointer to cfg80211 connect request
12238 *
12239 * This function is used to start the association process
12240 *
12241 * Return: 0 for success, non-zero for failure
12242 */
12243static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12244 struct net_device *ndev,
12245 struct cfg80211_connect_params *req)
12246{
12247 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012248 u16 channel;
12249#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12250 const u8 *bssid_hint = req->bssid_hint;
12251#else
12252 const u8 *bssid_hint = NULL;
12253#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012254 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12255 hdd_context_t *pHddCtx;
12256
12257 ENTER();
12258
Anurag Chouhan6d760662016-02-20 16:05:43 +053012259 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012260 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012261 return -EINVAL;
12262 }
12263
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012264 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012265 TRACE_CODE_HDD_CFG80211_CONNECT,
12266 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012267 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012268 hdd_device_mode_to_string(pAdapter->device_mode),
12269 pAdapter->device_mode);
12270
Krunal Sonib4326f22016-03-10 13:05:51 -080012271 if (pAdapter->device_mode != QDF_STA_MODE &&
12272 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012273 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274 hdd_device_mode_to_string(pAdapter->device_mode),
12275 pAdapter->device_mode);
12276 return -EINVAL;
12277 }
12278
12279 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12280 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012281 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 return -EINVAL;
12283 }
12284
12285 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012286 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012288
Naveen Rawat07332902016-07-27 09:13:17 -070012289 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012290 return status;
12291
Agrawal Ashishf156e942016-08-04 14:54:47 +053012292 wlan_hdd_disable_roaming(pAdapter);
12293
12294 /* Try disconnecting if already in connected state */
12295 status = wlan_hdd_try_disconnect(pAdapter);
12296 if (0 > status) {
12297 hdd_err("Failed to disconnect the existing connection");
12298 return -EALREADY;
12299 }
12300
12301 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012303 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012304 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305 pAdapter->device_mode),
12306 req->channel->hw_value, HW_MODE_20_MHZ)) {
12307 hdd_err("This concurrency combination is not allowed");
12308 return -ECONNREFUSED;
12309 }
12310 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012311 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012312 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012313 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12314 hdd_err("This concurrency combination is not allowed");
12315 return -ECONNREFUSED;
12316 }
12317 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012319 /*initialise security parameters */
12320 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12321
12322 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012323 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 return status;
12325 }
12326
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012327 if (req->channel)
12328 channel = req->channel->hw_value;
12329 else
12330 channel = 0;
12331 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12332 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012333 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012335 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012336 return status;
12337 }
12338 EXIT();
12339 return status;
12340}
12341
12342/**
12343 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12344 * @wiphy: Pointer to wiphy
12345 * @dev: Pointer to network device
12346 * @req: Pointer to cfg80211 connect request
12347 *
12348 * Return: 0 for success, non-zero for failure
12349 */
12350static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12351 struct net_device *ndev,
12352 struct cfg80211_connect_params *req)
12353{
12354 int ret;
12355 cds_ssr_protect(__func__);
12356 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12357 cds_ssr_unprotect(__func__);
12358
12359 return ret;
12360}
12361
12362/**
12363 * wlan_hdd_disconnect() - hdd disconnect api
12364 * @pAdapter: Pointer to adapter
12365 * @reason: Disconnect reason code
12366 *
12367 * This function is used to issue a disconnect request to SME
12368 *
12369 * Return: 0 for success, non-zero for failure
12370 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012371static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372{
12373 int status, result = 0;
12374 unsigned long rc;
12375 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12376 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12377
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012378 ENTER();
12379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380 status = wlan_hdd_validate_context(pHddCtx);
12381
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012382 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384
12385 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012386 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12388 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012389 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12391 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12392
12393 /*issue disconnect */
12394
12395 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12396 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012397 /*
12398 * Wait here instead of returning directly, this will block the next
12399 * connect command and allow processing of the scan for ssid and
12400 * the previous connect command in CSR. Else we might hit some
12401 * race conditions leading to SME and HDD out of sync.
12402 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012403 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012404 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012405 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012406 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 (int)status);
12408 pHddStaCtx->staDebugState = status;
12409 result = -EINVAL;
12410 goto disconnected;
12411 }
12412 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12413 msecs_to_jiffies
12414 (WLAN_WAIT_TIME_DISCONNECT));
12415
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012416 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012417 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 result = -ETIMEDOUT;
12419 }
12420disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012421 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12422#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12423 /* Sending disconnect event to userspace for kernel version < 3.11
12424 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12425 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012426 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012427 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12428 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429#endif
12430
12431 return result;
12432}
12433
12434/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012435 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12436 * @reason: ieee80211 reason code.
12437 *
12438 * This utility function helps log string conversion of reason code.
12439 *
12440 * Return: string conversion of reason code, if match found;
12441 * "Unknown" otherwise.
12442 */
12443static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12444{
12445 switch (reason) {
12446 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12447 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12448 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12449 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12450 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12451 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12452 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12453 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12454 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12455 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12456 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12457 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12458 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12459 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12460 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12461 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12462 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12463 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12464 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12465 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12466 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12467 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12468 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12469 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12470 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12471 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12472 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12473 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12474 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12475 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12476 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12477 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12478 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12479 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12480 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12481 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12482 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12483 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12484 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12485 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12486 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12487 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12488 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12489 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12490 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12491 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12492 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12493 default:
12494 return "Unknown";
12495 }
12496}
12497
12498/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012499 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12500 * @wiphy: Pointer to wiphy
12501 * @dev: Pointer to network device
12502 * @reason: Disconnect reason code
12503 *
12504 * This function is used to issue a disconnect request to SME
12505 *
12506 * Return: 0 for success, non-zero for failure
12507 */
12508static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12509 struct net_device *dev, u16 reason)
12510{
12511 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12512 int status;
12513 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12514 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12515#ifdef FEATURE_WLAN_TDLS
12516 uint8_t staIdx;
12517#endif
12518
12519 ENTER();
12520
Anurag Chouhan6d760662016-02-20 16:05:43 +053012521 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012522 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012523 return -EINVAL;
12524 }
12525
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012526 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12528 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012529 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 hdd_device_mode_to_string(pAdapter->device_mode),
12531 pAdapter->device_mode, reason);
12532
12533 status = wlan_hdd_validate_context(pHddCtx);
12534
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012535 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012537
12538 /* Issue disconnect request to SME, if station is in connected state */
12539 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12540 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12541 eCsrRoamDisconnectReason reasonCode =
12542 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12543 hdd_scaninfo_t *pScanInfo;
12544
12545 switch (reason) {
12546 case WLAN_REASON_MIC_FAILURE:
12547 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12548 break;
12549
12550 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12551 case WLAN_REASON_DISASSOC_AP_BUSY:
12552 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12553 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12554 break;
12555
12556 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12557 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12558 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12559 break;
12560
12561 case WLAN_REASON_DEAUTH_LEAVING:
12562 reasonCode =
12563 pHddCtx->config->
12564 gEnableDeauthToDisassocMap ?
12565 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12566 eCSR_DISCONNECT_REASON_DEAUTH;
12567 break;
12568 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12569 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12570 break;
12571 default:
12572 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12573 break;
12574 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012575 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012576 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012577 pScanInfo = &pAdapter->scan_info;
12578 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012579 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012580 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12581 eCSR_SCAN_ABORT_DEFAULT);
12582 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012583 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584#ifdef FEATURE_WLAN_TDLS
12585 /* First clean up the tdls peers if any */
12586 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12587 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12588 pAdapter->sessionId)
12589 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12590 uint8_t *mac;
12591 mac =
12592 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012593 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12594 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012595 pHddCtx->tdlsConnInfo[staIdx].staId,
12596 pAdapter->sessionId,
12597 MAC_ADDR_ARRAY(mac));
12598 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12599 (pAdapter),
12600 pAdapter->sessionId, mac);
12601 }
12602 }
12603#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012604 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012605 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012606 hdd_info("Disconnect request from user space with reason: %s",
12607 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012608 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12609 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012610 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 return -EINVAL;
12612 }
12613 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012614 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615 pHddStaCtx->conn_info.connState);
12616 }
12617
12618 return status;
12619}
12620
12621/**
12622 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12623 * @wiphy: Pointer to wiphy
12624 * @dev: Pointer to network device
12625 * @reason: Disconnect reason code
12626 *
12627 * Return: 0 for success, non-zero for failure
12628 */
12629static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12630 struct net_device *dev, u16 reason)
12631{
12632 int ret;
12633 cds_ssr_protect(__func__);
12634 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12635 cds_ssr_unprotect(__func__);
12636
12637 return ret;
12638}
12639
12640/**
12641 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12642 * @pAdapter: Pointer to adapter
12643 * @param: Pointer to IBSS parameters
12644 *
12645 * This function is used to initialize the security settings in IBSS mode
12646 *
12647 * Return: 0 for success, non-zero for failure
12648 */
12649static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12650 struct cfg80211_ibss_params
12651 *params)
12652{
12653 int status = 0;
12654 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12655 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12656 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12657
12658 ENTER();
12659
12660 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012661 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012662 pHddStaCtx->ibss_enc_key_installed = 0;
12663
12664 if (params->ie_len && (NULL != params->ie)) {
12665 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12666 params->ie_len, WLAN_EID_RSN)) {
12667 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12668 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12669 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12670 tDot11fIEWPA dot11WPAIE;
12671 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12672 u8 *ie;
12673
12674 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12675 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12676 params->ie_len,
12677 DOT11F_EID_WPA);
12678 if (NULL != ie) {
12679 pWextState->wpaVersion =
12680 IW_AUTH_WPA_VERSION_WPA;
12681 /* Unpack the WPA IE */
12682 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12683 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12684 &ie[2 + 4],
12685 ie[1] - 4, &dot11WPAIE);
12686 /*Extract the multicast cipher, the encType for unicast
12687 cipher for wpa-none is none */
12688 encryptionType =
12689 hdd_translate_wpa_to_csr_encryption_type
12690 (dot11WPAIE.multicast_cipher);
12691 }
12692 }
12693
12694 status =
12695 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12696 params->ie_len);
12697
12698 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012699 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012700 return status;
12701 }
12702 }
12703
12704 pWextState->roamProfile.AuthType.authType[0] =
12705 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12706
12707 if (params->privacy) {
12708 /* Security enabled IBSS, At this time there is no information
12709 * available about the security paramters, so initialise the
12710 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12711 * The correct security parameters will be updated later in
12712 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12713 * set inorder enable privacy bit in beacons
12714 */
12715
12716 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12717 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012718 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012719 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12720 pWextState->roamProfile.EncryptionType.numEntries = 1;
12721 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12722 encryptionType;
12723 return status;
12724}
12725
12726/**
12727 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12728 * @wiphy: Pointer to wiphy
12729 * @dev: Pointer to network device
12730 * @param: Pointer to IBSS join parameters
12731 *
12732 * This function is used to create/join an IBSS network
12733 *
12734 * Return: 0 for success, non-zero for failure
12735 */
12736static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12737 struct net_device *dev,
12738 struct cfg80211_ibss_params *params)
12739{
12740 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12741 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12742 tCsrRoamProfile *pRoamProfile;
12743 int status;
12744 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12745 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012746 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012748
12749 ENTER();
12750
Anurag Chouhan6d760662016-02-20 16:05:43 +053012751 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012752 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012753 return -EINVAL;
12754 }
12755
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012756 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012757 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12758 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012759 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 hdd_device_mode_to_string(pAdapter->device_mode),
12761 pAdapter->device_mode);
12762
12763 status = wlan_hdd_validate_context(pHddCtx);
12764
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012765 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012766 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012767
12768 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012769 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012770 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12771 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12772 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12773 int indx;
12774
12775 /* Get channel number */
12776 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 params->
12778 chandef.
12779 chan->
12780 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012781
12782 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12783 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012784 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 return -EOPNOTSUPP;
12786 }
12787
12788 for (indx = 0; indx < numChans; indx++) {
12789 if (channelNum == validChan[indx]) {
12790 break;
12791 }
12792 }
12793 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012794 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012795 return -EINVAL;
12796 }
12797 }
12798
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012799 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012800 HW_MODE_20_MHZ)) {
12801 hdd_err("This concurrency combination is not allowed");
12802 return -ECONNREFUSED;
12803 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012804
Krunal Soni3091bcc2016-06-23 12:28:21 -070012805 status = qdf_reset_connection_update();
12806 if (!QDF_IS_STATUS_SUCCESS(status))
12807 hdd_err("ERR: clear event failed");
12808
12809 status = cds_current_connections_update(pAdapter->sessionId,
12810 channelNum,
12811 SIR_UPDATE_REASON_JOIN_IBSS);
12812 if (QDF_STATUS_E_FAILURE == status) {
12813 hdd_err("ERROR: connections update failed!!");
12814 return -EINVAL;
12815 }
12816
12817 if (QDF_STATUS_SUCCESS == status) {
12818 status = qdf_wait_for_connection_update();
12819 if (!QDF_IS_STATUS_SUCCESS(status)) {
12820 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012821 return -EINVAL;
12822 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823 }
12824
12825 /*Try disconnecting if already in connected state */
12826 status = wlan_hdd_try_disconnect(pAdapter);
12827 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012828 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829 return -EALREADY;
12830 }
12831
12832 pRoamProfile = &pWextState->roamProfile;
12833
12834 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012835 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012836 return -EINVAL;
12837 }
12838
12839 /* enable selected protection checks in IBSS mode */
12840 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12841
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012842 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012843 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12844 pHddCtx->config->
12845 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012846 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012847 }
12848
12849 /* BSSID is provided by upper layers hence no need to AUTO generate */
12850 if (NULL != params->bssid) {
12851 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012852 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012853 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012854 return -EIO;
12855 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012856 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012857 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12858 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012859 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012860 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012861 return -EIO;
12862 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012863 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012864 }
12865 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12866 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12867 pRoamProfile->beaconInterval = params->beacon_interval;
12868 else {
12869 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012870 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012871 params->beacon_interval, pRoamProfile->beaconInterval);
12872 }
12873
12874 /* Set Channel */
12875 if (channelNum) {
12876 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012877 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012878 pRoamProfile->ChannelInfo.numOfChannels = 1;
12879 pHddStaCtx->conn_info.operationChannel = channelNum;
12880 pRoamProfile->ChannelInfo.ChannelList =
12881 &pHddStaCtx->conn_info.operationChannel;
12882 }
12883
12884 /* Initialize security parameters */
12885 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12886 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012887 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012888 return status;
12889 }
12890
12891 /* Issue connect start */
12892 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12893 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012894 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012895 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012896 operationChannel,
12897 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898
12899 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012900 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012901 return status;
12902 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012903 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 return 0;
12905}
12906
12907/**
12908 * wlan_hdd_cfg80211_join_ibss() - join ibss
12909 * @wiphy: Pointer to wiphy
12910 * @dev: Pointer to network device
12911 * @param: Pointer to IBSS join parameters
12912 *
12913 * This function is used to create/join an IBSS network
12914 *
12915 * Return: 0 for success, non-zero for failure
12916 */
12917static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12918 struct net_device *dev,
12919 struct cfg80211_ibss_params *params)
12920{
12921 int ret = 0;
12922
12923 cds_ssr_protect(__func__);
12924 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12925 cds_ssr_unprotect(__func__);
12926
12927 return ret;
12928}
12929
12930/**
12931 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12932 * @wiphy: Pointer to wiphy
12933 * @dev: Pointer to network device
12934 *
12935 * This function is used to leave an IBSS network
12936 *
12937 * Return: 0 for success, non-zero for failure
12938 */
12939static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12940 struct net_device *dev)
12941{
12942 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12943 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12944 tCsrRoamProfile *pRoamProfile;
12945 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12946 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012947 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012948 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012949 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012950
12951 ENTER();
12952
Anurag Chouhan6d760662016-02-20 16:05:43 +053012953 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012954 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 return -EINVAL;
12956 }
12957
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012958 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012959 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12960 pAdapter->sessionId,
12961 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12962 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012963 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012964 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012966 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012967 hdd_device_mode_to_string(pAdapter->device_mode),
12968 pAdapter->device_mode);
12969 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012970 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 return -EIO;
12972 }
12973
12974 pRoamProfile = &pWextState->roamProfile;
12975
12976 /* Issue disconnect only if interface type is set to IBSS */
12977 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012978 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 return -EINVAL;
12980 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012981 /* Clearing add IE of beacon */
12982 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
12983 sizeof(tSirMacAddr));
12984 updateIE.smeSessionId = pAdapter->sessionId;
12985 updateIE.ieBufferlength = 0;
12986 updateIE.pAdditionIEBuffer = NULL;
12987 updateIE.append = true;
12988 updateIE.notify = true;
12989 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
12990 &updateIE,
12991 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012992 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012993 }
12994
12995 /* Reset WNI_CFG_PROBE_RSP Flags */
12996 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997
12998 /* Issue Disconnect request */
12999 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13000 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13001 pAdapter->sessionId,
13002 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013003 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013004 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013005 hal_status);
13006 return -EAGAIN;
13007 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013008
13009 /* wait for mc thread to cleanup and then return to upper stack
13010 * so by the time upper layer calls the change interface, we are
13011 * all set to proceed further
13012 */
13013 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13014 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13015 if (!rc) {
13016 hdd_err("Failed to disconnect, timed out");
13017 return -ETIMEDOUT;
13018 }
13019
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013020 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021 return 0;
13022}
13023
13024/**
13025 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13026 * @wiphy: Pointer to wiphy
13027 * @dev: Pointer to network device
13028 *
13029 * This function is used to leave an IBSS network
13030 *
13031 * Return: 0 for success, non-zero for failure
13032 */
13033static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13034 struct net_device *dev)
13035{
13036 int ret = 0;
13037
13038 cds_ssr_protect(__func__);
13039 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13040 cds_ssr_unprotect(__func__);
13041
13042 return ret;
13043}
13044
13045/**
13046 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13047 * @wiphy: Pointer to wiphy
13048 * @changed: Parameters changed
13049 *
13050 * This function is used to set the phy parameters. RTS Threshold/FRAG
13051 * Threshold/Retry Count etc.
13052 *
13053 * Return: 0 for success, non-zero for failure
13054 */
13055static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13056 u32 changed)
13057{
13058 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13059 tHalHandle hHal = pHddCtx->hHal;
13060 int status;
13061
13062 ENTER();
13063
Anurag Chouhan6d760662016-02-20 16:05:43 +053013064 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013065 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 return -EINVAL;
13067 }
13068
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013069 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13071 NO_SESSION, wiphy->rts_threshold));
13072 status = wlan_hdd_validate_context(pHddCtx);
13073
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013074 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076
13077 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13078 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13079 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13080
13081 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13082 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013083 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 rts_threshold);
13085 return -EINVAL;
13086 }
13087
13088 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13089 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013090 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013091 rts_threshold);
13092 return -EIO;
13093 }
13094
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013095 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 }
13097
13098 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13099 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13100 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13101 wiphy->frag_threshold;
13102
13103 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13104 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013105 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013106 frag_threshold);
13107 return -EINVAL;
13108 }
13109
13110 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13111 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013112 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 frag_threshold);
13114 return -EIO;
13115 }
13116
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013117 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 }
13119
13120 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13121 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13122 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13123 wiphy->retry_short : wiphy->retry_long;
13124
13125 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13126 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013127 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 return -EINVAL;
13129 }
13130
13131 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13132 if (0 != sme_cfg_set_int(hHal,
13133 WNI_CFG_LONG_RETRY_LIMIT,
13134 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013135 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013136 retry_value);
13137 return -EIO;
13138 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013139 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13141 if (0 != sme_cfg_set_int(hHal,
13142 WNI_CFG_SHORT_RETRY_LIMIT,
13143 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013144 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145 retry_value);
13146 return -EIO;
13147 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013148 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013149 }
13150 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013151 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 return 0;
13153}
13154
13155/**
13156 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13157 * @wiphy: Pointer to wiphy
13158 * @changed: Parameters changed
13159 *
13160 * Return: 0 for success, non-zero for failure
13161 */
13162static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13163{
13164 int ret;
13165
13166 cds_ssr_protect(__func__);
13167 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13168 cds_ssr_unprotect(__func__);
13169
13170 return ret;
13171}
13172
13173/**
13174 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13175 * key
13176 * @wiphy: Pointer to wiphy
13177 * @dev: Pointer to network device
13178 * @key_index: Key index
13179 *
13180 * Return: 0
13181 */
13182static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13183 struct net_device *netdev,
13184 u8 key_index)
13185{
13186 ENTER();
13187 return 0;
13188}
13189
13190/**
13191 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13192 * wlan_hdd_set_default_mgmt_key
13193 * @wiphy: pointer to wiphy
13194 * @netdev: pointer to net_device structure
13195 * @key_index: key index
13196 *
13197 * Return: 0 on success, error number on failure
13198 */
13199static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13200 struct net_device *netdev,
13201 u8 key_index)
13202{
13203 int ret;
13204
13205 cds_ssr_protect(__func__);
13206 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13207 cds_ssr_unprotect(__func__);
13208
13209 return ret;
13210}
13211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013212/**
13213 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13214 * @wiphy: Pointer to wiphy
13215 * @dev: Pointer to network device
13216 * @params: Pointer to tx queue parameters
13217 *
13218 * Return: 0
13219 */
13220static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13221 struct net_device *dev,
13222 struct ieee80211_txq_params *params)
13223{
13224 ENTER();
13225 return 0;
13226}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227
13228/**
13229 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13230 * @wiphy: pointer to wiphy
13231 * @netdev: pointer to net_device structure
13232 * @params: pointer to ieee80211_txq_params
13233 *
13234 * Return: 0 on success, error number on failure
13235 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013236static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13237 struct net_device *dev,
13238 struct ieee80211_txq_params *params)
13239{
13240 int ret;
13241
13242 cds_ssr_protect(__func__);
13243 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13244 cds_ssr_unprotect(__func__);
13245
13246 return ret;
13247}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013248
13249/**
13250 * __wlan_hdd_cfg80211_del_station() - delete station v2
13251 * @wiphy: Pointer to wiphy
13252 * @param: Pointer to delete station parameter
13253 *
13254 * Return: 0 for success, non-zero for failure
13255 */
13256static
13257int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13258 struct net_device *dev,
13259 struct tagCsrDelStaParams *pDelStaParams)
13260{
13261 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13262 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013263 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013264 hdd_hostapd_state_t *hapd_state;
13265 int status;
13266 uint8_t staId;
13267 uint8_t *mac;
13268
13269 ENTER();
13270
Anurag Chouhan6d760662016-02-20 16:05:43 +053013271 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013272 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013273 return -EINVAL;
13274 }
13275
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013276 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013277 TRACE_CODE_HDD_CFG80211_DEL_STA,
13278 pAdapter->sessionId, pAdapter->device_mode));
13279
13280 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13281 status = wlan_hdd_validate_context(pHddCtx);
13282
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013283 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013285
13286 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13287
Krunal Sonib4326f22016-03-10 13:05:51 -080013288 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13289 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290
13291 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13292 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013293 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 return 0;
13295 }
13296
Anurag Chouhanc5548422016-02-24 18:33:27 +053013297 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013298 uint16_t i;
13299 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13300 if ((pAdapter->aStaInfo[i].isUsed) &&
13301 (!pAdapter->aStaInfo[i].
13302 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013303 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 mac,
13305 pAdapter->aStaInfo[i].
13306 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013307 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13309 hdd_ipa_wlan_evt(pAdapter,
13310 pAdapter->
13311 aStaInfo[i].
13312 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013313 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 mac);
13315 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013316 hdd_notice("Delete STA with MAC::"
13317 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 MAC_ADDR_ARRAY(mac));
13319
13320 if (pHddCtx->dev_dfs_cac_status ==
13321 DFS_CAC_IN_PROGRESS)
13322 goto fn_end;
13323
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013324 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013325 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013326 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013327 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013328 hdd_softap_sta_deauth(pAdapter,
13329 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013330 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013331 pAdapter->aStaInfo[i].
13332 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013333 qdf_status =
13334 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013335 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013336 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013337 if (!QDF_IS_STATUS_SUCCESS(
13338 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013339 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340 }
13341 }
13342 }
13343 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013344 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013346 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013348 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013349 hdd_notice("Skip DEL STA as this is not used::"
13350 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013351 MAC_ADDR_ARRAY(mac));
13352 return -ENOENT;
13353 }
13354
13355 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13356 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013357 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 }
13359
13360 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13361 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013362 hdd_notice("Skip DEL STA as deauth is in progress::"
13363 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 MAC_ADDR_ARRAY(mac));
13365 return -ENOENT;
13366 }
13367
13368 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13369
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013370 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 MAC_ADDR_ARRAY(mac));
13372
13373 /* Case: SAP in ACS selected DFS ch and client connected
13374 * Now Radar detected. Then if random channel is another
13375 * DFS ch then new CAC is initiated and no TX allowed.
13376 * So do not send any mgmt frames as it will timeout
13377 * during CAC.
13378 */
13379
13380 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13381 goto fn_end;
13382
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013383 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013384 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13385 (pAdapter), pAdapter->sessionId,
13386 (uint8_t *)&pDelStaParams->peerMacAddr,
13387 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013388 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013389 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013390 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 pAdapter->aStaInfo[staId].isDeauthInProgress =
13392 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013393 hdd_notice("STA removal failed for ::"
13394 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013395 MAC_ADDR_ARRAY(mac));
13396 return -ENOENT;
13397 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013398 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013399 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013400 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013401 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013402 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 }
13404 }
13405 }
13406
13407fn_end:
13408 EXIT();
13409 return 0;
13410}
13411
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013412#if defined(USE_CFG80211_DEL_STA_V2)
13413/**
13414 * wlan_hdd_del_station() - delete station wrapper
13415 * @adapter: pointer to the hdd adapter
13416 *
13417 * Return: None
13418 */
13419void wlan_hdd_del_station(hdd_adapter_t *adapter)
13420{
13421 struct station_del_parameters del_sta;
13422 del_sta.mac = NULL;
13423 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13424 del_sta.reason_code = eCsrForcedDeauthSta;
13425
13426 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13427 &del_sta);
13428}
13429#else
13430void wlan_hdd_del_station(hdd_adapter_t *adapter)
13431{
13432 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13433}
13434#endif
13435
13436#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437/**
13438 * wlan_hdd_cfg80211_del_station() - delete station v2
13439 * @wiphy: Pointer to wiphy
13440 * @param: Pointer to delete station parameter
13441 *
13442 * Return: 0 for success, non-zero for failure
13443 */
13444int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13445 struct net_device *dev,
13446 struct station_del_parameters *param)
13447#else
13448/**
13449 * wlan_hdd_cfg80211_del_station() - delete station
13450 * @wiphy: Pointer to wiphy
13451 * @mac: Pointer to station mac address
13452 *
13453 * Return: 0 for success, non-zero for failure
13454 */
13455#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13456int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13457 struct net_device *dev,
13458 const uint8_t *mac)
13459#else
13460int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13461 struct net_device *dev,
13462 uint8_t *mac)
13463#endif
13464#endif
13465{
13466 int ret;
13467 struct tagCsrDelStaParams delStaParams;
13468
13469 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013470#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013472 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013473 return -EINVAL;
13474 }
13475 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13476 param->subtype, &delStaParams);
13477#else
13478 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13479 (SIR_MAC_MGMT_DEAUTH >> 4),
13480 &delStaParams);
13481#endif
13482 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13483 cds_ssr_unprotect(__func__);
13484
13485 return ret;
13486}
13487
13488/**
13489 * __wlan_hdd_cfg80211_add_station() - add station
13490 * @wiphy: Pointer to wiphy
13491 * @mac: Pointer to station mac address
13492 * @pmksa: Pointer to add station parameter
13493 *
13494 * Return: 0 for success, non-zero for failure
13495 */
13496static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13497 struct net_device *dev,
13498 const uint8_t *mac,
13499 struct station_parameters *params)
13500{
13501 int status = -EPERM;
13502#ifdef FEATURE_WLAN_TDLS
13503 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13504 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13505 u32 mask, set;
13506
13507 ENTER();
13508
Anurag Chouhan6d760662016-02-20 16:05:43 +053013509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013510 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 return -EINVAL;
13512 }
13513
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013514 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013515 TRACE_CODE_HDD_CFG80211_ADD_STA,
13516 pAdapter->sessionId, params->listen_interval));
13517
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013518 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013519 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520
13521 mask = params->sta_flags_mask;
13522
13523 set = params->sta_flags_set;
13524
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013525 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 MAC_ADDR_ARRAY(mac));
13527
13528 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13529 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13530 status =
13531 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13532 }
13533 }
13534#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013535 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013536 return status;
13537}
13538
13539/**
13540 * wlan_hdd_cfg80211_add_station() - add station
13541 * @wiphy: Pointer to wiphy
13542 * @mac: Pointer to station mac address
13543 * @pmksa: Pointer to add station parameter
13544 *
13545 * Return: 0 for success, non-zero for failure
13546 */
13547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13548static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13549 struct net_device *dev,
13550 const uint8_t *mac,
13551 struct station_parameters *params)
13552#else
13553static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13554 struct net_device *dev, uint8_t *mac,
13555 struct station_parameters *params)
13556#endif
13557{
13558 int ret;
13559
13560 cds_ssr_protect(__func__);
13561 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13562 cds_ssr_unprotect(__func__);
13563
13564 return ret;
13565}
13566
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567/**
13568 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13569 * @wiphy: Pointer to wiphy
13570 * @dev: Pointer to network device
13571 * @pmksa: Pointer to set pmksa parameter
13572 *
13573 * Return: 0 for success, non-zero for failure
13574 */
13575static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13576 struct net_device *dev,
13577 struct cfg80211_pmksa *pmksa)
13578{
13579 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13580 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13581 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013582 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 int status;
13584 tPmkidCacheInfo pmk_id;
13585
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013586 ENTER();
13587
Anurag Chouhan6d760662016-02-20 16:05:43 +053013588 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013589 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 return -EINVAL;
13591 }
13592
13593 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013594 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013595 return -EINVAL;
13596 }
13597
13598 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013599 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013600 pmksa->bssid, pmksa->pmkid);
13601 return -EINVAL;
13602 }
13603
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013604 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605 MAC_ADDR_ARRAY(pmksa->bssid));
13606
13607 status = wlan_hdd_validate_context(pHddCtx);
13608
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013609 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611
13612 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13613
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013614 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13615 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013616
13617 /* Add to the PMKSA ID Cache in CSR */
13618 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13619 &pmk_id, 1, false);
13620
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013621 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013622 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13623 pAdapter->sessionId, result));
13624
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013625 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013626 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627}
13628
13629/**
13630 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13631 * @wiphy: Pointer to wiphy
13632 * @dev: Pointer to network device
13633 * @pmksa: Pointer to set pmksa parameter
13634 *
13635 * Return: 0 for success, non-zero for failure
13636 */
13637static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13638 struct net_device *dev,
13639 struct cfg80211_pmksa *pmksa)
13640{
13641 int ret;
13642
13643 cds_ssr_protect(__func__);
13644 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13645 cds_ssr_unprotect(__func__);
13646
13647 return ret;
13648}
13649
13650/**
13651 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13652 * @wiphy: Pointer to wiphy
13653 * @dev: Pointer to network device
13654 * @pmksa: Pointer to pmksa parameter
13655 *
13656 * Return: 0 for success, non-zero for failure
13657 */
13658static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13659 struct net_device *dev,
13660 struct cfg80211_pmksa *pmksa)
13661{
13662 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13663 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13664 tHalHandle halHandle;
13665 int status = 0;
13666
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013667 ENTER();
13668
Anurag Chouhan6d760662016-02-20 16:05:43 +053013669 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013670 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 return -EINVAL;
13672 }
13673
13674 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013675 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013676 return -EINVAL;
13677 }
13678
13679 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013680 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013681 return -EINVAL;
13682 }
13683
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013684 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013685 MAC_ADDR_ARRAY(pmksa->bssid));
13686
13687 status = wlan_hdd_validate_context(pHddCtx);
13688
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013689 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691
13692 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13693
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013694 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013695 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13696 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013698 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013699 sme_roam_del_pmkid_from_cache(halHandle,
13700 pAdapter->sessionId, pmksa->bssid,
13701 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013702 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 MAC_ADDR_ARRAY(pmksa->bssid));
13704 status = -EINVAL;
13705 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013706 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013707 return status;
13708}
13709
13710/**
13711 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13712 * @wiphy: Pointer to wiphy
13713 * @dev: Pointer to network device
13714 * @pmksa: Pointer to pmksa parameter
13715 *
13716 * Return: 0 for success, non-zero for failure
13717 */
13718static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13719 struct net_device *dev,
13720 struct cfg80211_pmksa *pmksa)
13721{
13722 int ret;
13723
13724 cds_ssr_protect(__func__);
13725 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13726 cds_ssr_unprotect(__func__);
13727
13728 return ret;
13729
13730}
13731
13732/**
13733 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13734 * @wiphy: Pointer to wiphy
13735 * @dev: Pointer to network device
13736 *
13737 * Return: 0 for success, non-zero for failure
13738 */
13739static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13740 struct net_device *dev)
13741{
13742 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13743 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13744 tHalHandle halHandle;
13745 int status = 0;
13746
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013747 ENTER();
13748
Anurag Chouhan6d760662016-02-20 16:05:43 +053013749 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013750 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751 return -EINVAL;
13752 }
13753
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013754 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755
13756 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13757 status = wlan_hdd_validate_context(pHddCtx);
13758
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013759 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761
13762 /* Retrieve halHandle */
13763 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13764
13765 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013766 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013767 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13768 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013769 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 status = -EINVAL;
13771 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013772 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013773 return status;
13774}
13775
13776/**
13777 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13778 * @wiphy: Pointer to wiphy
13779 * @dev: Pointer to network device
13780 *
13781 * Return: 0 for success, non-zero for failure
13782 */
13783static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13784 struct net_device *dev)
13785{
13786 int ret;
13787
13788 cds_ssr_protect(__func__);
13789 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13790 cds_ssr_unprotect(__func__);
13791
13792 return ret;
13793}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013794
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013795#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013796/**
13797 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13798 * @wiphy: Pointer to wiphy
13799 * @dev: Pointer to network device
13800 * @ftie: Pointer to fast transition ie parameter
13801 *
13802 * Return: 0 for success, non-zero for failure
13803 */
13804static int
13805__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13806 struct net_device *dev,
13807 struct cfg80211_update_ft_ies_params *ftie)
13808{
13809 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13810 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13811 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13812 int status;
13813
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013814 ENTER();
13815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013816 status = wlan_hdd_validate_context(hdd_ctx);
13817 if (status)
13818 return status;
13819
Anurag Chouhan6d760662016-02-20 16:05:43 +053013820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013821 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 return -EINVAL;
13823 }
13824
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013825 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13827 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13828 /* Added for debug on reception of Re-assoc Req. */
13829 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013830 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013832 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013834 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013836
13837 /* Pass the received FT IEs to SME */
13838 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13839 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013840 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841 return 0;
13842}
13843
13844/**
13845 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13846 * @wiphy: Pointer to wiphy
13847 * @dev: Pointer to network device
13848 * @ftie: Pointer to fast transition ie parameter
13849 *
13850 * Return: 0 for success, non-zero for failure
13851 */
13852static int
13853wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13854 struct net_device *dev,
13855 struct cfg80211_update_ft_ies_params *ftie)
13856{
13857 int ret;
13858
13859 cds_ssr_protect(__func__);
13860 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13861 cds_ssr_unprotect(__func__);
13862
13863 return ret;
13864}
13865#endif
13866
13867#ifdef WLAN_FEATURE_GTK_OFFLOAD
13868/**
13869 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13870 * @callbackContext: Callback context
13871 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13872 *
13873 * Callback rountine called upon receiving response for get offload info
13874 *
13875 * Return: none
13876 */
13877void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13878 tpSirGtkOffloadGetInfoRspParams
13879 pGtkOffloadGetInfoRsp)
13880{
13881 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13882 uint8_t tempReplayCounter[8];
13883 hdd_station_ctx_t *pHddStaCtx;
13884
13885 ENTER();
13886
13887 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013888 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889 return;
13890 }
13891
13892 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013893 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013894 return;
13895 }
13896
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013897 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013898 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013899 return;
13900 }
13901
13902 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13903 /* Update replay counter */
13904 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13905 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13906
13907 {
13908 /* changing from little to big endian since supplicant
13909 * works on big endian format
13910 */
13911 int i;
13912 uint8_t *p =
13913 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13914
13915 for (i = 0; i < 8; i++) {
13916 tempReplayCounter[7 - i] = (uint8_t) p[i];
13917 }
13918 }
13919
13920 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013921 cfg80211_gtk_rekey_notify(pAdapter->dev,
13922 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 tempReplayCounter, GFP_KERNEL);
13924}
13925
13926/**
13927 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13928 * @wiphy: Pointer to wiphy
13929 * @dev: Pointer to network device
13930 * @data: Pointer to rekey data
13931 *
13932 * This function is used to offload GTK rekeying job to the firmware.
13933 *
13934 * Return: 0 for success, non-zero for failure
13935 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013936static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13938 struct net_device *dev,
13939 struct cfg80211_gtk_rekey_data *data)
13940{
13941 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13942 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13943 hdd_station_ctx_t *pHddStaCtx;
13944 tHalHandle hHal;
13945 int result;
13946 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013947 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013948
13949 ENTER();
13950
Anurag Chouhan6d760662016-02-20 16:05:43 +053013951 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013952 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 return -EINVAL;
13954 }
13955
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013956 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13958 pAdapter->sessionId, pAdapter->device_mode));
13959
13960 result = wlan_hdd_validate_context(pHddCtx);
13961
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013962 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013963 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013964
13965 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13966 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13967 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013968 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013969 return -EAGAIN;
13970 }
13971
13972 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13973 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
13974 NL80211_KCK_LEN);
13975 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
13976 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053013977 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013978 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 {
13980 /* changing from big to little endian since driver
13981 * works on little endian format
13982 */
13983 uint8_t *p =
13984 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
13985 ullKeyReplayCounter;
13986 int i;
13987
13988 for (i = 0; i < 8; i++) {
13989 p[7 - i] = data->replay_ctr[i];
13990 }
13991 }
13992
13993 if (true == pHddCtx->hdd_wlan_suspended) {
13994 /* if wlan is suspended, enable GTK offload directly from here */
13995 memcpy(&hddGtkOffloadReqParams,
13996 &pHddStaCtx->gtkOffloadReqParams,
13997 sizeof(tSirGtkOffloadParams));
13998 status =
13999 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14000 pAdapter->sessionId);
14001
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014002 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014003 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004 status);
14005 return -EINVAL;
14006 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014007 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014008 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014009 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014010 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014011 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 return result;
14013}
14014
14015/**
14016 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14017 * @wiphy: Pointer to wiphy
14018 * @dev: Pointer to network device
14019 * @data: Pointer to rekey data
14020 *
14021 * This function is used to offload GTK rekeying job to the firmware.
14022 *
14023 * Return: 0 for success, non-zero for failure
14024 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014025static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14027 struct net_device *dev,
14028 struct cfg80211_gtk_rekey_data *data)
14029{
14030 int ret;
14031
14032 cds_ssr_protect(__func__);
14033 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14034 cds_ssr_unprotect(__func__);
14035
14036 return ret;
14037}
14038#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14039
14040/**
14041 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14042 * @wiphy: Pointer to wiphy
14043 * @dev: Pointer to network device
14044 * @param: Pointer to access control parameter
14045 *
14046 * Return: 0 for success, non-zero for failure
14047 */
14048static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14049 struct net_device *dev,
14050 const struct cfg80211_acl_data *params)
14051{
14052 int i;
14053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14054 hdd_hostapd_state_t *pHostapdState;
14055 tsap_Config_t *pConfig;
14056 v_CONTEXT_t p_cds_context = NULL;
14057 hdd_context_t *pHddCtx;
14058 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014059 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060
14061 ENTER();
14062
Anurag Chouhan6d760662016-02-20 16:05:43 +053014063 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014064 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014065 return -EINVAL;
14066 }
14067
14068 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014069 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014070 return -EINVAL;
14071 }
14072
14073 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14074 status = wlan_hdd_validate_context(pHddCtx);
14075
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014076 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014078
14079 p_cds_context = pHddCtx->pcds_context;
14080 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14081
14082 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014083 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014084 return -EINVAL;
14085 }
14086
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014087 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014088 params->n_acl_entries);
14089
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014090 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014091 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14092 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014093 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014094 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14095
14096 /* default value */
14097 pConfig->num_accept_mac = 0;
14098 pConfig->num_deny_mac = 0;
14099
14100 /**
14101 * access control policy
14102 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14103 * listed in hostapd.deny file.
14104 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14105 * listed in hostapd.accept file.
14106 */
14107 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14108 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14109 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14110 params->acl_policy) {
14111 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14112 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014113 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 params->acl_policy);
14115 return -ENOTSUPP;
14116 }
14117
14118 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14119 pConfig->num_accept_mac = params->n_acl_entries;
14120 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014121 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14122 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014123 MAC_ADDR_ARRAY(
14124 params->mac_addrs[i].addr));
14125
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014126 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 params->mac_addrs[i].addr,
14128 sizeof(qcmacaddr));
14129 }
14130 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14131 pConfig->num_deny_mac = params->n_acl_entries;
14132 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014133 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14134 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 MAC_ADDR_ARRAY(
14136 params->mac_addrs[i].addr));
14137
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014138 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014139 params->mac_addrs[i].addr,
14140 sizeof(qcmacaddr));
14141 }
14142 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014143 qdf_status = wlansap_set_mac_acl(
14144 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014145 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014146 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014147 return -EINVAL;
14148 }
14149 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014150 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014151 hdd_device_mode_to_string(pAdapter->device_mode),
14152 pAdapter->device_mode);
14153 return -EINVAL;
14154 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014155 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014156 return 0;
14157}
14158
14159/**
14160 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14161 * __wlan_hdd_cfg80211_set_mac_acl
14162 * @wiphy: pointer to wiphy structure
14163 * @dev: pointer to net_device
14164 * @params: pointer to cfg80211_acl_data
14165 *
14166 * Return; 0 on success, error number otherwise
14167 */
14168static int
14169wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14170 struct net_device *dev,
14171 const struct cfg80211_acl_data *params)
14172{
14173 int ret;
14174
14175 cds_ssr_protect(__func__);
14176 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14177 cds_ssr_unprotect(__func__);
14178
14179 return ret;
14180}
14181
14182#ifdef WLAN_NL80211_TESTMODE
14183#ifdef FEATURE_WLAN_LPHB
14184/**
14185 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14186 * @pHddCtx: Pointer to hdd context
14187 * @lphbInd: Pointer to low power heart beat indication parameter
14188 *
14189 * Return: none
14190 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014191static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14192 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014193{
14194 struct sk_buff *skb;
14195
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014196 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014198 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014199 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200
14201 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014202 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203 return;
14204 }
14205
14206 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14207 wiphy, sizeof(tSirLPHBInd),
14208 GFP_ATOMIC);
14209 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014210 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 return;
14212 }
14213
14214 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014215 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 goto nla_put_failure;
14217 }
14218 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014219 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220 goto nla_put_failure;
14221 }
14222 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014223 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014224 goto nla_put_failure;
14225 }
14226 cfg80211_testmode_event(skb, GFP_ATOMIC);
14227 return;
14228
14229nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014230 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014231 kfree_skb(skb);
14232
14233 return;
14234}
14235#endif /* FEATURE_WLAN_LPHB */
14236
14237/**
14238 * __wlan_hdd_cfg80211_testmode() - test mode
14239 * @wiphy: Pointer to wiphy
14240 * @data: Data pointer
14241 * @len: Data length
14242 *
14243 * Return: 0 for success, non-zero for failure
14244 */
14245static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14246 void *data, int len)
14247{
14248 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14249 int err;
14250 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14251
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014252 ENTER();
14253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254 err = wlan_hdd_validate_context(pHddCtx);
14255 if (err)
14256 return err;
14257
14258 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14259 len, wlan_hdd_tm_policy);
14260 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014261 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014262 return err;
14263 }
14264
14265 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014266 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 return -EINVAL;
14268 }
14269
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014270 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014271 TRACE_CODE_HDD_CFG80211_TESTMODE,
14272 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014273 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14274#ifdef FEATURE_WLAN_LPHB
14275 /* Low Power Heartbeat configuration request */
14276 case WLAN_HDD_TM_CMD_WLAN_HB:
14277 {
14278 int buf_len;
14279 void *buf;
14280 tSirLPHBReq *hb_params = NULL;
14281 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014282 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014283
14284 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014285 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014286 return -EINVAL;
14287 }
14288
14289 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14290 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14291
14292 hb_params_temp = (tSirLPHBReq *) buf;
14293 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14294 && (hb_params_temp->params.lphbTcpParamReq.
14295 timePeriodSec == 0))
14296 return -EINVAL;
14297
14298 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014299 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014301 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014302 return -ENOMEM;
14303 }
14304
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014305 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 smeStatus =
14307 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14308 hb_params,
14309 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014310 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014311 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014312 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313 }
14314 return 0;
14315 }
14316#endif /* FEATURE_WLAN_LPHB */
14317
14318#if defined(QCA_WIFI_FTM)
14319 case WLAN_HDD_TM_CMD_WLAN_FTM:
14320 {
14321 int buf_len;
14322 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014323 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014324 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014325 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014326 return -EINVAL;
14327 }
14328
14329 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14330 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14331
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014332 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333
14334 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14335
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014336 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 err = -EBUSY;
14338 break;
14339 }
14340#endif
14341
14342 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014343 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14345 return -EOPNOTSUPP;
14346 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014347 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014348 return err;
14349}
14350
14351/**
14352 * wlan_hdd_cfg80211_testmode() - test mode
14353 * @wiphy: Pointer to wiphy
14354 * @dev: Pointer to network device
14355 * @data: Data pointer
14356 * @len: Data length
14357 *
14358 * Return: 0 for success, non-zero for failure
14359 */
14360static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14361#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14362 struct wireless_dev *wdev,
14363#endif
14364 void *data, int len)
14365{
14366 int ret;
14367
14368 cds_ssr_protect(__func__);
14369 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14370 cds_ssr_unprotect(__func__);
14371
14372 return ret;
14373}
14374
14375#if defined(QCA_WIFI_FTM)
14376/**
14377 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14378 * @buf: Pointer to buffer
14379 * @buf_len: Buffer length
14380 *
14381 * Return: none
14382 */
14383void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14384{
14385 struct sk_buff *skb;
14386 hdd_context_t *hdd_ctx;
14387
14388 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014389 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014390 return;
14391 }
14392
Anurag Chouhan6d760662016-02-20 16:05:43 +053014393 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014394 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014395 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396 return;
14397 }
14398
14399 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14400 buf_len, GFP_KERNEL);
14401 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014402 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014403 return;
14404 }
14405
14406 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14407 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14408 goto nla_put_failure;
14409
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014410 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014411
14412 cfg80211_testmode_event(skb, GFP_KERNEL);
14413 return;
14414
14415nla_put_failure:
14416 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014417 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014418}
14419#endif
14420#endif /* CONFIG_NL80211_TESTMODE */
14421
14422#ifdef QCA_HT_2040_COEX
14423/**
14424 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14425 * @wiphy: Pointer to wiphy
14426 * @dev: Pointer to network device
14427 * @chandef: Pointer to channel definition parameter
14428 *
14429 * Return: 0 for success, non-zero for failure
14430 */
14431static int
14432__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14433 struct net_device *dev,
14434 struct cfg80211_chan_def *chandef)
14435{
14436 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14437 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014438 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014439 tSmeConfigParams sme_config;
14440 bool cbModeChange;
14441
Anurag Chouhan6d760662016-02-20 16:05:43 +053014442 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014443 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014444 return -EINVAL;
14445 }
14446
14447 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14448 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014449 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014451
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014452 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453 sme_get_config_param(pHddCtx->hHal, &sme_config);
14454 switch (chandef->width) {
14455 case NL80211_CHAN_WIDTH_20:
14456 if (sme_config.csrConfig.channelBondingMode24GHz !=
14457 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14458 sme_config.csrConfig.channelBondingMode24GHz =
14459 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14460 sme_update_config(pHddCtx->hHal, &sme_config);
14461 cbModeChange = true;
14462 }
14463 break;
14464
14465 case NL80211_CHAN_WIDTH_40:
14466 if (sme_config.csrConfig.channelBondingMode24GHz ==
14467 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14468 if (NL80211_CHAN_HT40MINUS ==
14469 cfg80211_get_chandef_type(chandef))
14470 sme_config.csrConfig.channelBondingMode24GHz =
14471 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14472 else
14473 sme_config.csrConfig.channelBondingMode24GHz =
14474 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14475 sme_update_config(pHddCtx->hHal, &sme_config);
14476 cbModeChange = true;
14477 }
14478 break;
14479
14480 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014481 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482 return -EINVAL;
14483 }
14484
14485 if (!cbModeChange)
14486 return 0;
14487
Krunal Sonib4326f22016-03-10 13:05:51 -080014488 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014489 return 0;
14490
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014491 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014492 sme_config.csrConfig.channelBondingMode24GHz);
14493
14494 /* Change SAP ht2040 mode */
14495 status = hdd_set_sap_ht2040_mode(pAdapter,
14496 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014497 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014498 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 return -EINVAL;
14500 }
14501
14502 return 0;
14503}
14504
14505/**
14506 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14507 * @wiphy: Pointer to wiphy
14508 * @dev: Pointer to network device
14509 * @chandef: Pointer to channel definition parameter
14510 *
14511 * Return: 0 for success, non-zero for failure
14512 */
14513static int
14514wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14515 struct net_device *dev,
14516 struct cfg80211_chan_def *chandef)
14517{
14518 int ret;
14519
14520 cds_ssr_protect(__func__);
14521 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14522 cds_ssr_unprotect(__func__);
14523
14524 return ret;
14525}
14526#endif
14527
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014528#ifdef CHANNEL_SWITCH_SUPPORTED
14529/**
14530 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14531 * channel in SAP/GO
14532 * @wiphy: wiphy pointer
14533 * @dev: dev pointer.
14534 * @csa_params: Change channel params
14535 *
14536 * This function is called to switch channel in SAP/GO
14537 *
14538 * Return: 0 if success else return non zero
14539 */
14540static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14541 struct net_device *dev,
14542 struct cfg80211_csa_settings *csa_params)
14543{
14544 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14545 hdd_context_t *hdd_ctx;
14546 uint8_t channel;
14547 uint16_t freq;
14548 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014549 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014550
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014551 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014552 csa_params->chandef.chan->center_freq);
14553
14554 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14555 ret = wlan_hdd_validate_context(hdd_ctx);
14556
14557 if (0 != ret)
14558 return ret;
14559
Krunal Sonib4326f22016-03-10 13:05:51 -080014560 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14561 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014562 return -ENOTSUPP;
14563
14564 freq = csa_params->chandef.chan->center_freq;
14565 channel = cds_freq_to_chan(freq);
14566
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014567 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14568
14569 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014570 return ret;
14571}
14572
14573/**
14574 * wlan_hdd_cfg80211_channel_switch()- function to switch
14575 * channel in SAP/GO
14576 * @wiphy: wiphy pointer
14577 * @dev: dev pointer.
14578 * @csa_params: Change channel params
14579 *
14580 * This function is called to switch channel in SAP/GO
14581 *
14582 * Return: 0 if success else return non zero
14583 */
14584static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14585 struct net_device *dev,
14586 struct cfg80211_csa_settings *csa_params)
14587{
14588 int ret;
14589
14590 cds_ssr_protect(__func__);
14591 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14592 cds_ssr_unprotect(__func__);
14593 return ret;
14594}
14595#endif
14596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014597/**
14598 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14599 * translation from NL to policy manager type
14600 * @type: Generic connection mode type defined in NL
14601 *
14602 *
14603 * This function provides the type translation
14604 *
14605 * Return: cds_con_mode enum
14606 */
14607enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14608 enum nl80211_iftype type)
14609{
14610 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14611 switch (type) {
14612 case NL80211_IFTYPE_STATION:
14613 mode = CDS_STA_MODE;
14614 break;
14615 case NL80211_IFTYPE_P2P_CLIENT:
14616 mode = CDS_P2P_CLIENT_MODE;
14617 break;
14618 case NL80211_IFTYPE_P2P_GO:
14619 mode = CDS_P2P_GO_MODE;
14620 break;
14621 case NL80211_IFTYPE_AP:
14622 mode = CDS_SAP_MODE;
14623 break;
14624 case NL80211_IFTYPE_ADHOC:
14625 mode = CDS_IBSS_MODE;
14626 break;
14627 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014628 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629 type);
14630 }
14631 return mode;
14632}
14633
14634/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014635 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14636 * @wiphy: Handle to struct wiphy to get handle to module context.
14637 * @chandef: Contains information about the capture channel to be set.
14638 *
14639 * This interface is called if and only if monitor mode interface alone is
14640 * active.
14641 *
14642 * Return: 0 success or error code on failure.
14643 */
14644static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14645 struct cfg80211_chan_def *chandef)
14646{
14647 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14648 hdd_adapter_t *adapter;
14649 hdd_station_ctx_t *sta_ctx;
14650 struct hdd_mon_set_ch_info *ch_info;
14651 QDF_STATUS status;
14652 tHalHandle hal_hdl;
14653 struct qdf_mac_addr bssid;
14654 tCsrRoamProfile roam_profile;
14655 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014656 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014657 int ret;
14658 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14659
14660 ENTER();
14661
14662 ret = wlan_hdd_validate_context(hdd_ctx);
14663 if (ret)
14664 return ret;
14665
14666 hal_hdl = hdd_ctx->hHal;
14667
14668 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14669 if (!adapter)
14670 return -EIO;
14671
14672 hdd_info("%s: set monitor mode Channel %d and freq %d",
14673 adapter->dev->name, chan_num, chandef->chan->center_freq);
14674
14675 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14676 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014677 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14678 roam_profile.ChannelInfo.numOfChannels = 1;
14679 roam_profile.phyMode = ch_info->phy_mode;
14680 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014681 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014682
14683 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14684 QDF_MAC_ADDR_SIZE);
14685
14686 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014687 /*
14688 * CDS api expects secondary channel for calculating
14689 * the channel params
14690 */
14691 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14692 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14693 if (chan_num >= 1 && chan_num <= 5)
14694 sec_ch = chan_num + 4;
14695 else if (chan_num >= 6 && chan_num <= 13)
14696 sec_ch = chan_num - 4;
14697 }
14698 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014699 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14700 &roam_profile);
14701 if (status) {
14702 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14703 status);
14704 ret = qdf_status_to_os_return(status);
14705 return ret;
14706 }
14707 EXIT();
14708 return 0;
14709}
14710
14711/**
14712 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14713 * @wiphy: Handle to struct wiphy to get handle to module context.
14714 * @chandef: Contains information about the capture channel to be set.
14715 *
14716 * This interface is called if and only if monitor mode interface alone is
14717 * active.
14718 *
14719 * Return: 0 success or error code on failure.
14720 */
14721static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14722 struct cfg80211_chan_def *chandef)
14723{
14724 int ret;
14725
14726 cds_ssr_protect(__func__);
14727 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14728 cds_ssr_unprotect(__func__);
14729 return ret;
14730}
14731
14732/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 * struct cfg80211_ops - cfg80211_ops
14734 *
14735 * @add_virtual_intf: Add virtual interface
14736 * @del_virtual_intf: Delete virtual interface
14737 * @change_virtual_intf: Change virtual interface
14738 * @change_station: Change station
14739 * @add_beacon: Add beacon in sap mode
14740 * @del_beacon: Delete beacon in sap mode
14741 * @set_beacon: Set beacon in sap mode
14742 * @start_ap: Start ap
14743 * @change_beacon: Change beacon
14744 * @stop_ap: Stop ap
14745 * @change_bss: Change bss
14746 * @add_key: Add key
14747 * @get_key: Get key
14748 * @del_key: Delete key
14749 * @set_default_key: Set default key
14750 * @set_channel: Set channel
14751 * @scan: Scan
14752 * @connect: Connect
14753 * @disconnect: Disconnect
14754 * @join_ibss = Join ibss
14755 * @leave_ibss = Leave ibss
14756 * @set_wiphy_params = Set wiphy params
14757 * @set_tx_power = Set tx power
14758 * @get_tx_power = get tx power
14759 * @remain_on_channel = Remain on channel
14760 * @cancel_remain_on_channel = Cancel remain on channel
14761 * @mgmt_tx = Tx management frame
14762 * @mgmt_tx_cancel_wait = Cancel management tx wait
14763 * @set_default_mgmt_key = Set default management key
14764 * @set_txq_params = Set tx queue parameters
14765 * @get_station = Get station
14766 * @set_power_mgmt = Set power management
14767 * @del_station = Delete station
14768 * @add_station = Add station
14769 * @set_pmksa = Set pmksa
14770 * @del_pmksa = Delete pmksa
14771 * @flush_pmksa = Flush pmksa
14772 * @update_ft_ies = Update FT IEs
14773 * @tdls_mgmt = Tdls management
14774 * @tdls_oper = Tdls operation
14775 * @set_rekey_data = Set rekey data
14776 * @sched_scan_start = Scheduled scan start
14777 * @sched_scan_stop = Scheduled scan stop
14778 * @resume = Resume wlan
14779 * @suspend = Suspend wlan
14780 * @set_mac_acl = Set mac acl
14781 * @testmode_cmd = Test mode command
14782 * @set_ap_chanwidth = Set AP channel bandwidth
14783 * @dump_survey = Dump survey
14784 * @key_mgmt_set_pmk = Set pmk key management
14785 */
14786static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14787 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14788 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14789 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14790 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791 .start_ap = wlan_hdd_cfg80211_start_ap,
14792 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14793 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014794 .change_bss = wlan_hdd_cfg80211_change_bss,
14795 .add_key = wlan_hdd_cfg80211_add_key,
14796 .get_key = wlan_hdd_cfg80211_get_key,
14797 .del_key = wlan_hdd_cfg80211_del_key,
14798 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14799 .scan = wlan_hdd_cfg80211_scan,
14800 .connect = wlan_hdd_cfg80211_connect,
14801 .disconnect = wlan_hdd_cfg80211_disconnect,
14802 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14803 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14804 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14805 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14806 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14807 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14808 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14809 .mgmt_tx = wlan_hdd_mgmt_tx,
14810 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14811 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14812 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014813 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814 .get_station = wlan_hdd_cfg80211_get_station,
14815 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14816 .del_station = wlan_hdd_cfg80211_del_station,
14817 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14819 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14820 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014821#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014822 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14823#endif
14824#ifdef FEATURE_WLAN_TDLS
14825 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14826 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14827#endif
14828#ifdef WLAN_FEATURE_GTK_OFFLOAD
14829 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14830#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14831#ifdef FEATURE_WLAN_SCAN_PNO
14832 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14833 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14834#endif /*FEATURE_WLAN_SCAN_PNO */
14835 .resume = wlan_hdd_cfg80211_resume_wlan,
14836 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14837 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14838#ifdef WLAN_NL80211_TESTMODE
14839 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14840#endif
14841#ifdef QCA_HT_2040_COEX
14842 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14843#endif
14844 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014845#ifdef CHANNEL_SWITCH_SUPPORTED
14846 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14847#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014848 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014849#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14850 defined(CFG80211_ABORT_SCAN)
14851 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14852#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853};