blob: eb8fedd49527467563a3becc50103836c1bc6c1d [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
Jeff Johnson1f61b612016-02-12 16:28:33 -08001803 ENTER_DEV(wdev->netdev);
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);
1891 EXIT();
1892 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893nla_put_failure:
1894 kfree_skb(skb);
1895 return -EINVAL;
1896}
1897
1898/**
1899 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1900 * @wiphy: pointer to wireless wiphy structure.
1901 * @wdev: pointer to wireless_dev structure.
1902 * @data: Pointer to the data to be passed via vendor interface
1903 * @data_len:Length of the data to be passed
1904 *
1905 * Return: Return the Success or Failure code.
1906 */
1907static int
1908wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1909 struct wireless_dev *wdev,
1910 const void *data, int data_len)
1911{
1912 int ret = 0;
1913
1914 cds_ssr_protect(__func__);
1915 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1916 data, data_len);
1917 cds_ssr_unprotect(__func__);
1918
1919 return ret;
1920}
1921
1922/**
1923 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1924 * @wiphy: pointer to wireless wiphy structure.
1925 * @wdev: pointer to wireless_dev structure.
1926 * @data: Pointer to the data to be passed via vendor interface
1927 * @data_len:Length of the data to be passed
1928 *
1929 * Set the MAC address that is to be used for scanning.
1930 *
1931 * Return: Return the Success or Failure code.
1932 */
1933static int
1934__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1935 struct wireless_dev *wdev,
1936 const void *data,
1937 int data_len)
1938{
1939 tpSirScanMacOui pReqMsg = NULL;
1940 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1941 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301942 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 int ret;
1944
Jeff Johnson1f61b612016-02-12 16:28:33 -08001945 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946
Anurag Chouhan6d760662016-02-20 16:05:43 +05301947 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 hdd_err("Command not allowed in FTM mode");
1949 return -EPERM;
1950 }
1951
1952 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301953 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955
1956 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001957 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958 return -ENOTSUPP;
1959 }
1960
1961 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1962 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001963 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 return -EINVAL;
1965 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301966 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001968 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969 return -ENOMEM;
1970 }
1971 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001972 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 goto fail;
1974 }
1975 nla_memcpy(&pReqMsg->oui[0],
1976 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1977 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001978 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 pReqMsg->oui[1], pReqMsg->oui[2]);
1980 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301981 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001982 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 goto fail;
1984 }
1985 return 0;
1986fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301987 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 return -EINVAL;
1989}
1990
1991/**
1992 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1993 * @wiphy: pointer to wireless wiphy structure.
1994 * @wdev: pointer to wireless_dev structure.
1995 * @data: Pointer to the data to be passed via vendor interface
1996 * @data_len:Length of the data to be passed
1997 *
1998 * Set the MAC address that is to be used for scanning. This is an
1999 * SSR-protecting wrapper function.
2000 *
2001 * Return: Return the Success or Failure code.
2002 */
2003static int
2004wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2005 struct wireless_dev *wdev,
2006 const void *data,
2007 int data_len)
2008{
2009 int ret;
2010
2011 cds_ssr_protect(__func__);
2012 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2013 data, data_len);
2014 cds_ssr_unprotect(__func__);
2015
2016 return ret;
2017}
2018
2019/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302020 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2021 * @wiphy: pointer phy adapter
2022 * @wdev: pointer to wireless device structure
2023 * @data: pointer to data buffer
2024 * @data_len: length of data
2025 *
2026 * This routine will give concurrency matrix
2027 *
2028 * Return: int status code
2029 */
2030static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2031 struct wireless_dev *wdev,
2032 const void *data,
2033 int data_len)
2034{
2035 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2036 uint8_t i, feature_sets, max_feature_sets;
2037 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2038 struct sk_buff *reply_skb;
2039 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2040 int ret;
2041
2042 ENTER_DEV(wdev->netdev);
2043
2044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2045 hdd_err("Command not allowed in FTM mode");
2046 return -EPERM;
2047 }
2048
2049 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302050 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302051 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302052
2053 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2054 data, data_len, NULL)) {
2055 hdd_err("Invalid ATTR");
2056 return -EINVAL;
2057 }
2058
2059 /* Parse and fetch max feature set */
2060 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2061 hdd_err("Attr max feature set size failed");
2062 return -EINVAL;
2063 }
2064 max_feature_sets = nla_get_u32(tb[
2065 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2066 hdd_info("Max feature set size: %d", max_feature_sets);
2067
2068 /* Fill feature combination matrix */
2069 feature_sets = 0;
2070 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2071 WIFI_FEATURE_P2P;
2072 /* Add more feature combinations here */
2073
2074 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2075 hdd_info("Number of feature sets:%d", feature_sets);
2076 hdd_info("Feature set matrix");
2077 for (i = 0; i < feature_sets; i++)
2078 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2079
2080 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2081 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2082 if (!reply_skb) {
2083 hdd_err("Feature set matrix: buffer alloc fail");
2084 return -ENOMEM;
2085 }
2086
2087 if (nla_put_u32(reply_skb,
2088 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2089 feature_sets) ||
2090 nla_put(reply_skb,
2091 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2092 sizeof(u32) * feature_sets,
2093 feature_set_matrix)) {
2094 hdd_err("nla put fail");
2095 kfree_skb(reply_skb);
2096 return -EINVAL;
2097 }
2098 return cfg80211_vendor_cmd_reply(reply_skb);
2099}
2100
2101/**
2102 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2103 * @wiphy: pointer to wireless wiphy structure.
2104 * @wdev: pointer to wireless_dev structure.
2105 * @data: Pointer to the data to be passed via vendor interface
2106 * @data_len:Length of the data to be passed
2107 *
2108 * Retrieves the concurrency feature set matrix
2109 *
2110 * Return: 0 on success, negative errno on failure
2111 */
2112static int
2113wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2114 struct wireless_dev *wdev,
2115 const void *data,
2116 int data_len)
2117{
2118 int ret;
2119
2120 cds_ssr_protect(__func__);
2121 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2122 data, data_len);
2123 cds_ssr_unprotect(__func__);
2124
2125 return ret;
2126}
2127
2128/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2130 * @feature_flags: pointer to the byte array of features.
2131 * @feature: Feature to be turned ON in the byte array.
2132 *
2133 * Return: None
2134 *
2135 * This is called to turn ON or SET the feature flag for the requested feature.
2136 **/
2137#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002138static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2139 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140{
2141 uint32_t index;
2142 uint8_t bit_mask;
2143
2144 index = feature / NUM_BITS_IN_BYTE;
2145 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2146 feature_flags[index] |= bit_mask;
2147}
2148
2149/**
2150 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2151 * @wiphy: pointer to wireless wiphy structure.
2152 * @wdev: pointer to wireless_dev structure.
2153 * @data: Pointer to the data to be passed via vendor interface
2154 * @data_len:Length of the data to be passed
2155 *
2156 * This is called when wlan driver needs to send supported feature set to
2157 * supplicant upon a request/query from the supplicant.
2158 *
2159 * Return: Return the Success or Failure code.
2160 **/
2161#define MAX_CONCURRENT_CHAN_ON_24G 2
2162#define MAX_CONCURRENT_CHAN_ON_5G 2
2163static int
2164__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2165 struct wireless_dev *wdev,
2166 const void *data, int data_len)
2167{
2168 struct sk_buff *skb = NULL;
2169 uint32_t dbs_capability = 0;
2170 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302171 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 int ret_val;
2173
2174 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2175 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2176
Jeff Johnson1f61b612016-02-12 16:28:33 -08002177 ENTER_DEV(wdev->netdev);
2178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2180 if (ret_val)
2181 return ret_val;
2182
Anurag Chouhan6d760662016-02-20 16:05:43 +05302183 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 hdd_err("Command not allowed in FTM mode");
2185 return -EPERM;
2186 }
2187
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002188 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002189 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190 wlan_hdd_cfg80211_set_feature(feature_flags,
2191 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2192 }
2193
2194 wlan_hdd_cfg80211_set_feature(feature_flags,
2195 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2196 if (wma_is_scan_simultaneous_capable())
2197 wlan_hdd_cfg80211_set_feature(feature_flags,
2198 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002199
2200 if (wma_is_p2p_lo_capable())
2201 wlan_hdd_cfg80211_set_feature(feature_flags,
2202 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2203
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2205 NLMSG_HDRLEN);
2206
2207 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002208 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209 return -ENOMEM;
2210 }
2211
2212 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2213 sizeof(feature_flags), feature_flags))
2214 goto nla_put_failure;
2215
2216 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302217 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 if (one_by_one_dbs)
2219 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2220
2221 if (two_by_two_dbs)
2222 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2223
2224 if (!one_by_one_dbs && !two_by_two_dbs)
2225 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2226 } else {
2227 hdd_err("wma_get_dbs_hw_mode failed");
2228 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2229 }
2230
2231 hdd_info("dbs_capability is %d", dbs_capability);
2232
2233 if (nla_put_u32(skb,
2234 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2235 MAX_CONCURRENT_CHAN_ON_24G))
2236 goto nla_put_failure;
2237
2238 if (nla_put_u32(skb,
2239 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2240 MAX_CONCURRENT_CHAN_ON_5G))
2241 goto nla_put_failure;
2242
2243 return cfg80211_vendor_cmd_reply(skb);
2244
2245nla_put_failure:
2246 kfree_skb(skb);
2247 return -EINVAL;
2248}
2249
2250/**
2251 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2252 * @wiphy: pointer to wireless wiphy structure.
2253 * @wdev: pointer to wireless_dev structure.
2254 * @data: Pointer to the data to be passed via vendor interface
2255 * @data_len:Length of the data to be passed
2256 *
2257 * This is called when wlan driver needs to send supported feature set to
2258 * supplicant upon a request/query from the supplicant.
2259 *
2260 * Return: Return the Success or Failure code.
2261 */
2262static int
2263wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2264 struct wireless_dev *wdev,
2265 const void *data, int data_len)
2266{
2267 int ret;
2268
2269 cds_ssr_protect(__func__);
2270 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2271 data, data_len);
2272 cds_ssr_unprotect(__func__);
2273
2274 return ret;
2275}
2276
2277
2278/**
2279 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2280 * @wiphy: The wiphy structure
2281 * @wdev: The wireless device
2282 * @data: Data passed by framework
2283 * @data_len: Parameters to be configured passed as data
2284 *
2285 * The roaming related parameters are configured by the framework
2286 * using this interface.
2287 *
2288 * Return: Return either success or failure code.
2289 */
2290static int
2291__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2292 struct wireless_dev *wdev, const void *data, int data_len)
2293{
2294 struct net_device *dev = wdev->netdev;
2295 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2296 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2297 uint8_t session_id;
2298 struct roam_ext_params roam_params;
2299 uint32_t cmd_type, req_id;
2300 struct nlattr *curr_attr;
2301 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2302 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2303 int rem, i;
2304 uint32_t buf_len = 0;
2305 int ret;
2306
Jeff Johnson1f61b612016-02-12 16:28:33 -08002307 ENTER_DEV(dev);
2308
Anurag Chouhan6d760662016-02-20 16:05:43 +05302309 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310 hdd_err("Command not allowed in FTM mode");
2311 return -EPERM;
2312 }
2313
2314 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302315 if (ret)
2316 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317
2318 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2319 data, data_len,
2320 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002321 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002322 return -EINVAL;
2323 }
2324 /* Parse and fetch Command Type*/
2325 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002326 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 goto fail;
2328 }
2329 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302330 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2332 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002333 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002334 goto fail;
2335 }
2336 req_id = nla_get_u32(
2337 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002338 hdd_debug("Req Id (%d)", req_id);
2339 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340 switch (cmd_type) {
2341 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2342 i = 0;
2343 nla_for_each_nested(curr_attr,
2344 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2345 rem) {
2346 if (nla_parse(tb2,
2347 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2348 nla_data(curr_attr), nla_len(curr_attr),
2349 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002350 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 goto fail;
2352 }
2353 /* Parse and Fetch allowed SSID list*/
2354 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002355 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 goto fail;
2357 }
2358 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2359 /*
2360 * Upper Layers include a null termination character.
2361 * Check for the actual permissible length of SSID and
2362 * also ensure not to copy the NULL termination
2363 * character to the driver buffer.
2364 */
2365 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2366 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2367 nla_memcpy(
2368 roam_params.ssid_allowed_list[i].ssId,
2369 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2370 buf_len - 1);
2371 roam_params.ssid_allowed_list[i].length =
2372 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002373 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 roam_params.ssid_allowed_list[i].length,
2375 roam_params.ssid_allowed_list[i].ssId,
2376 roam_params.ssid_allowed_list[i].length);
2377 i++;
2378 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002379 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 }
2381 }
2382 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002383 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 roam_params.num_ssid_allowed_list);
2385 sme_update_roam_params(pHddCtx->hHal, session_id,
2386 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2387 break;
2388 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2389 /* Parse and fetch 5G Boost Threshold */
2390 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002391 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 goto fail;
2393 }
2394 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2395 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002396 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002397 roam_params.raise_rssi_thresh_5g);
2398 /* Parse and fetch 5G Penalty Threshold */
2399 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002400 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 goto fail;
2402 }
2403 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2404 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002405 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002406 roam_params.drop_rssi_thresh_5g);
2407 /* Parse and fetch 5G Boost Factor */
2408 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002409 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002410 goto fail;
2411 }
2412 roam_params.raise_factor_5g = nla_get_u32(
2413 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002414 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 roam_params.raise_factor_5g);
2416 /* Parse and fetch 5G Penalty factor */
2417 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002418 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 goto fail;
2420 }
2421 roam_params.drop_factor_5g = nla_get_u32(
2422 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002423 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 roam_params.drop_factor_5g);
2425 /* Parse and fetch 5G Max Boost */
2426 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002427 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 goto fail;
2429 }
2430 roam_params.max_raise_rssi_5g = nla_get_u32(
2431 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002432 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002433 roam_params.max_raise_rssi_5g);
2434 /* Parse and fetch Rssi Diff */
2435 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002436 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 goto fail;
2438 }
2439 roam_params.rssi_diff = nla_get_s32(
2440 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002441 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 roam_params.rssi_diff);
2443 /* Parse and fetch Alert Rssi Threshold */
2444 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002445 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 goto fail;
2447 }
2448 roam_params.alert_rssi_threshold = nla_get_u32(
2449 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002450 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 roam_params.alert_rssi_threshold);
2452 sme_update_roam_params(pHddCtx->hHal, session_id,
2453 roam_params,
2454 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2455 break;
2456 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2457 /* Parse and fetch Activate Good Rssi Roam */
2458 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 goto fail;
2461 }
2462 roam_params.good_rssi_roam = nla_get_s32(
2463 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002464 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 roam_params.good_rssi_roam);
2466 sme_update_roam_params(pHddCtx->hHal, session_id,
2467 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2468 break;
2469 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2470 /* Parse and fetch number of preferred BSSID */
2471 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 goto fail;
2474 }
2475 roam_params.num_bssid_favored = nla_get_u32(
2476 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002477 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 roam_params.num_bssid_favored);
2479 i = 0;
2480 nla_for_each_nested(curr_attr,
2481 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2482 rem) {
2483 if (nla_parse(tb2,
2484 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2485 nla_data(curr_attr), nla_len(curr_attr),
2486 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002487 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 goto fail;
2489 }
2490 /* Parse and fetch MAC address */
2491 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002492 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 goto fail;
2494 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002495 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302497 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002498 hdd_debug(MAC_ADDRESS_STR,
2499 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002500 /* Parse and fetch preference factor*/
2501 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002502 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 goto fail;
2504 }
2505 roam_params.bssid_favored_factor[i] = nla_get_u32(
2506 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002507 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508 roam_params.bssid_favored_factor[i]);
2509 i++;
2510 }
2511 sme_update_roam_params(pHddCtx->hHal, session_id,
2512 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2513 break;
2514 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2515 /* Parse and fetch number of blacklist BSSID */
2516 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002517 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002518 goto fail;
2519 }
2520 roam_params.num_bssid_avoid_list = nla_get_u32(
2521 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002522 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 roam_params.num_bssid_avoid_list);
2524 i = 0;
2525 nla_for_each_nested(curr_attr,
2526 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2527 rem) {
2528 if (nla_parse(tb2,
2529 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2530 nla_data(curr_attr), nla_len(curr_attr),
2531 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002532 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 goto fail;
2534 }
2535 /* Parse and fetch MAC address */
2536 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002537 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 goto fail;
2539 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002540 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302542 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002543 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002545 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 i++;
2547 }
2548 sme_update_roam_params(pHddCtx->hHal, session_id,
2549 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2550 break;
2551 }
2552 return 0;
2553fail:
2554 return -EINVAL;
2555}
2556
2557/**
2558 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2559 * @wiphy: pointer to wireless wiphy structure.
2560 * @wdev: pointer to wireless_dev structure.
2561 * @data: Pointer to the data to be passed via vendor interface
2562 * @data_len:Length of the data to be passed
2563 *
2564 * Return: Return the Success or Failure code.
2565 */
2566static int
2567wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2568 struct wireless_dev *wdev,
2569 const void *data,
2570 int data_len)
2571{
2572 int ret;
2573
2574 cds_ssr_protect(__func__);
2575 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2576 data, data_len);
2577 cds_ssr_unprotect(__func__);
2578
2579 return ret;
2580}
2581
2582static const struct nla_policy
2583wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2584 +1] = {
2585 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2586};
2587
2588/**
2589 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2590 * @hdd_ctx: HDD context
2591 * @device_mode: device mode
2592 * Return: bool
2593 */
2594static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002595 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596{
2597 hdd_adapter_t *adapter;
2598 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2599 hdd_ap_ctx_t *ap_ctx;
2600 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302601 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302603 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002604 &adapter_node);
2605
2606 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302607 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002608 adapter = adapter_node->pAdapter;
2609
2610 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002611 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 ap_ctx =
2613 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2614
2615 /*
2616 * if there is SAP already running on DFS channel,
2617 * do not disable scan on dfs channels. Note that
2618 * with SAP on DFS, there cannot be conurrency on
2619 * single radio. But then we can have multiple
2620 * radios !!
2621 */
2622 if (CHANNEL_STATE_DFS ==
2623 cds_get_channel_state(
2624 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002625 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 return true;
2627 }
2628 }
2629
2630 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002631 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002632 sta_ctx =
2633 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2634
2635 /*
2636 * if STA is already connected on DFS channel,
2637 * do not disable scan on dfs channels
2638 */
2639 if (hdd_conn_is_connected(sta_ctx) &&
2640 (CHANNEL_STATE_DFS ==
2641 cds_get_channel_state(
2642 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002643 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002644 return true;
2645 }
2646 }
2647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302648 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 adapter_node,
2650 &next);
2651 adapter_node = next;
2652 }
2653
2654 return false;
2655}
2656
2657/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002658 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2659 * @hdd_ctx: HDD context within host driver
2660 * @adapter: Adapter pointer
2661 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2662 *
2663 * Loops through devices to see who is operating on DFS channels
2664 * and then disables/enables DFS channels by calling SME API.
2665 * Fails the disable request if any device is active on a DFS channel.
2666 *
2667 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002669
2670int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2671 hdd_adapter_t *adapter,
2672 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302675 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677
2678 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2679 if (no_dfs_flag) {
2680 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002681 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682
2683 if (true == status)
2684 return -EOPNOTSUPP;
2685
2686 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002687 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688
2689 if (true == status)
2690 return -EOPNOTSUPP;
2691 }
2692
2693 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2694
2695 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2696
2697 /*
2698 * call the SME API to tunnel down the new channel list
2699 * to the firmware
2700 */
2701 status = sme_handle_dfs_chan_scan(
2702 h_hal, hdd_ctx->config->enableDFSChnlScan);
2703
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302704 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 ret_val = 0;
2706
2707 /*
2708 * Clear the SME scan cache also. Note that the
2709 * clearing of scan results is independent of session;
2710 * so no need to iterate over
2711 * all sessions
2712 */
2713 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302714 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 ret_val = -EPERM;
2716 }
2717
2718 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002719 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 ret_val = 0;
2721 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002722 return ret_val;
2723}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002725/**
2726 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2727 * @wiphy: corestack handler
2728 * @wdev: wireless device
2729 * @data: data
2730 * @data_len: data length
2731 * Return: success(0) or reason code for failure
2732 */
2733static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2734 struct wireless_dev *wdev,
2735 const void *data,
2736 int data_len)
2737{
2738 struct net_device *dev = wdev->netdev;
2739 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2740 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2741 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2742 int ret_val;
2743 uint32_t no_dfs_flag = 0;
2744
Jeff Johnson1f61b612016-02-12 16:28:33 -08002745 ENTER_DEV(dev);
2746
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002747 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302748 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002749 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002750
2751 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2752 data, data_len,
2753 wlan_hdd_set_no_dfs_flag_config_policy)) {
2754 hdd_err("invalid attr");
2755 return -EINVAL;
2756 }
2757
2758 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2759 hdd_err("attr dfs flag failed");
2760 return -EINVAL;
2761 }
2762
2763 no_dfs_flag = nla_get_u32(
2764 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2765
Jeff Johnson020db452016-06-29 14:37:26 -07002766 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002767
2768 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002769 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002770 return -EINVAL;
2771 }
2772
2773 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2774 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002775 return ret_val;
2776}
2777
2778/**
2779 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2780 *
2781 * @wiphy: wiphy device pointer
2782 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002783 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 * @data_len: Buffer length
2785 *
2786 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2787 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2788 *
2789 * Return: EOK or other error codes.
2790 */
2791
2792static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2793 struct wireless_dev *wdev,
2794 const void *data,
2795 int data_len)
2796{
2797 int ret;
2798
2799 cds_ssr_protect(__func__);
2800 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2801 data, data_len);
2802 cds_ssr_unprotect(__func__);
2803
2804 return ret;
2805}
2806
Manikandan Mohan80dea792016-04-28 16:36:48 -07002807static const struct nla_policy
2808wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2809 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2810};
2811
2812/**
2813 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2814 * @wiphy: wiphy device pointer
2815 * @wdev: wireless device pointer
2816 * @data: Vendor command data buffer
2817 * @data_len: Buffer length
2818 *
2819 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2820 * setup WISA Mode features.
2821 *
2822 * Return: Success(0) or reason code for failure
2823 */
2824static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2825 struct wireless_dev *wdev, const void *data, int data_len)
2826{
2827 struct net_device *dev = wdev->netdev;
2828 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2829 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2830 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2831 struct sir_wisa_params wisa;
2832 int ret_val;
2833 QDF_STATUS status;
2834 bool wisa_mode;
2835
2836 ENTER_DEV(dev);
2837 ret_val = wlan_hdd_validate_context(hdd_ctx);
2838 if (ret_val)
2839 goto err;
2840
2841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2842 hdd_err("Command not allowed in FTM mode");
2843 return -EPERM;
2844 }
2845
2846 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2847 wlan_hdd_wisa_cmd_policy)) {
2848 hdd_err("Invalid WISA cmd attributes");
2849 ret_val = -EINVAL;
2850 goto err;
2851 }
2852 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2853 hdd_err("Invalid WISA mode");
2854 ret_val = -EINVAL;
2855 goto err;
2856 }
2857
2858 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2859 hdd_info("WISA Mode: %d", wisa_mode);
2860 wisa.mode = wisa_mode;
2861 wisa.vdev_id = adapter->sessionId;
2862 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002863 if (!QDF_IS_STATUS_SUCCESS(status)) {
2864 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002865 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002866 }
2867 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2868 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2869 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002870err:
2871 EXIT();
2872 return ret_val;
2873}
2874
2875/**
2876 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2877 * @wiphy: corestack handler
2878 * @wdev: wireless device
2879 * @data: data
2880 * @data_len: data length
2881 *
2882 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2883 * setup WISA mode features.
2884 *
2885 * Return: Success(0) or reason code for failure
2886 */
2887static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2888 struct wireless_dev *wdev,
2889 const void *data,
2890 int data_len)
2891{
2892 int ret;
2893
2894 cds_ssr_protect(__func__);
2895 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2896 cds_ssr_unprotect(__func__);
2897
2898 return ret;
2899}
2900
Anurag Chouhan96919482016-07-13 16:36:57 +05302901/*
2902 * define short names for the global vendor params
2903 * used by __wlan_hdd_cfg80211_get_station_cmd()
2904 */
2905#define STATION_INVALID \
2906 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2907#define STATION_INFO \
2908 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2909#define STATION_ASSOC_FAIL_REASON \
2910 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2911#define STATION_MAX \
2912 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2913
2914static const struct nla_policy
2915hdd_get_station_policy[STATION_MAX + 1] = {
2916 [STATION_INFO] = {.type = NLA_FLAG},
2917 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2918};
2919
2920/**
2921 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2922 * @hdd_ctx: HDD context within host driver
2923 * @wdev: wireless device
2924 *
2925 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2926 * Validate cmd attributes and send the station info to upper layers.
2927 *
2928 * Return: Success(0) or reason code for failure
2929 */
2930static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2931 hdd_adapter_t *adapter)
2932{
2933 struct sk_buff *skb = NULL;
2934 uint32_t nl_buf_len;
2935 hdd_station_ctx_t *hdd_sta_ctx;
2936
2937 nl_buf_len = NLMSG_HDRLEN;
2938 nl_buf_len += sizeof(uint32_t);
2939 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2940
2941 if (!skb) {
2942 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2943 return -ENOMEM;
2944 }
2945
2946 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2947
2948 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2949 hdd_sta_ctx->conn_info.assoc_status_code)) {
2950 hdd_err("put fail");
2951 goto fail;
2952 }
2953 return cfg80211_vendor_cmd_reply(skb);
2954fail:
2955 if (skb)
2956 kfree_skb(skb);
2957 return -EINVAL;
2958}
2959
2960/**
2961 * hdd_map_auth_type() - transform auth type specific to
2962 * vendor command
2963 * @auth_type: csr auth type
2964 *
2965 * Return: Success(0) or reason code for failure
2966 */
2967static int hdd_convert_auth_type(uint32_t auth_type)
2968{
2969 uint32_t ret_val;
2970
2971 switch (auth_type) {
2972 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2973 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2974 break;
2975 case eCSR_AUTH_TYPE_SHARED_KEY:
2976 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2977 break;
2978 case eCSR_AUTH_TYPE_WPA:
2979 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2980 break;
2981 case eCSR_AUTH_TYPE_WPA_PSK:
2982 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2983 break;
2984 case eCSR_AUTH_TYPE_AUTOSWITCH:
2985 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
2986 break;
2987 case eCSR_AUTH_TYPE_WPA_NONE:
2988 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
2989 break;
2990 case eCSR_AUTH_TYPE_RSN:
2991 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
2992 break;
2993 case eCSR_AUTH_TYPE_RSN_PSK:
2994 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
2995 break;
2996 case eCSR_AUTH_TYPE_FT_RSN:
2997 ret_val = QCA_WLAN_AUTH_TYPE_FT;
2998 break;
2999 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3000 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3001 break;
3002 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3003 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3004 break;
3005 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3006 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3007 break;
3008 case eCSR_AUTH_TYPE_CCKM_WPA:
3009 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3010 break;
3011 case eCSR_AUTH_TYPE_CCKM_RSN:
3012 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3013 break;
3014 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3015 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3016 break;
3017 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3018 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3019 break;
3020 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3021 case eCSR_AUTH_TYPE_FAILED:
3022 case eCSR_AUTH_TYPE_NONE:
3023 default:
3024 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3025 break;
3026 }
3027 return ret_val;
3028}
3029
3030/**
3031 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3032 * vendor command
3033 * @dot11mode: dot11mode
3034 *
3035 * Return: Success(0) or reason code for failure
3036 */
3037static int hdd_convert_dot11mode(uint32_t dot11mode)
3038{
3039 uint32_t ret_val;
3040
3041 switch (dot11mode) {
3042 case eCSR_CFG_DOT11_MODE_11A:
3043 ret_val = QCA_WLAN_802_11_MODE_11A;
3044 break;
3045 case eCSR_CFG_DOT11_MODE_11B:
3046 ret_val = QCA_WLAN_802_11_MODE_11B;
3047 break;
3048 case eCSR_CFG_DOT11_MODE_11G:
3049 ret_val = QCA_WLAN_802_11_MODE_11G;
3050 break;
3051 case eCSR_CFG_DOT11_MODE_11N:
3052 ret_val = QCA_WLAN_802_11_MODE_11N;
3053 break;
3054 case eCSR_CFG_DOT11_MODE_11AC:
3055 ret_val = QCA_WLAN_802_11_MODE_11AC;
3056 break;
3057 case eCSR_CFG_DOT11_MODE_AUTO:
3058 case eCSR_CFG_DOT11_MODE_ABG:
3059 default:
3060 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3061 }
3062 return ret_val;
3063}
3064
3065/**
3066 * hdd_add_tx_bitrate() - add tx bitrate attribute
3067 * @skb: pointer to sk buff
3068 * @hdd_sta_ctx: pointer to hdd station context
3069 * @idx: attribute index
3070 *
3071 * Return: Success(0) or reason code for failure
3072 */
3073static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3074 hdd_station_ctx_t *hdd_sta_ctx,
3075 int idx)
3076{
3077 struct nlattr *nla_attr;
3078 uint32_t bitrate, bitrate_compat;
3079
3080 nla_attr = nla_nest_start(skb, idx);
3081 if (!nla_attr)
3082 goto fail;
3083 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3084 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3085
3086 /* report 16-bit bitrate only if we can */
3087 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3088 if (bitrate > 0 &&
3089 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3090 hdd_err("put fail");
3091 goto fail;
3092 }
3093 if (bitrate_compat > 0 &&
3094 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3095 hdd_err("put fail");
3096 goto fail;
3097 }
3098 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3099 hdd_sta_ctx->conn_info.txrate.nss)) {
3100 hdd_err("put fail");
3101 goto fail;
3102 }
3103 nla_nest_end(skb, nla_attr);
3104 return 0;
3105fail:
3106 return -EINVAL;
3107}
3108
3109/**
3110 * hdd_add_sta_info() - add station info attribute
3111 * @skb: pointer to sk buff
3112 * @hdd_sta_ctx: pointer to hdd station context
3113 * @idx: attribute index
3114 *
3115 * Return: Success(0) or reason code for failure
3116 */
3117static int32_t hdd_add_sta_info(struct sk_buff *skb,
3118 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3119{
3120 struct nlattr *nla_attr;
3121
3122 nla_attr = nla_nest_start(skb, idx);
3123 if (!nla_attr)
3124 goto fail;
3125 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3126 (hdd_sta_ctx->conn_info.signal + 100))) {
3127 hdd_err("put fail");
3128 goto fail;
3129 }
3130 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3131 goto fail;
3132 nla_nest_end(skb, nla_attr);
3133 return 0;
3134fail:
3135 return -EINVAL;
3136}
3137
3138/**
3139 * hdd_add_survey_info() - add survey info attribute
3140 * @skb: pointer to sk buff
3141 * @hdd_sta_ctx: pointer to hdd station context
3142 * @idx: attribute index
3143 *
3144 * Return: Success(0) or reason code for failure
3145 */
3146static int32_t hdd_add_survey_info(struct sk_buff *skb,
3147 hdd_station_ctx_t *hdd_sta_ctx,
3148 int idx)
3149{
3150 struct nlattr *nla_attr;
3151
3152 nla_attr = nla_nest_start(skb, idx);
3153 if (!nla_attr)
3154 goto fail;
3155 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3156 hdd_sta_ctx->conn_info.freq) ||
3157 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3158 (hdd_sta_ctx->conn_info.noise + 100))) {
3159 hdd_err("put fail");
3160 goto fail;
3161 }
3162 nla_nest_end(skb, nla_attr);
3163 return 0;
3164fail:
3165 return -EINVAL;
3166}
3167
3168/**
3169 * hdd_add_link_standard_info() - add link info attribute
3170 * @skb: pointer to sk buff
3171 * @hdd_sta_ctx: pointer to hdd station context
3172 * @idx: attribute index
3173 *
3174 * Return: Success(0) or reason code for failure
3175 */
3176static int32_t
3177hdd_add_link_standard_info(struct sk_buff *skb,
3178 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3179{
3180 struct nlattr *nla_attr;
3181
3182 nla_attr = nla_nest_start(skb, idx);
3183 if (!nla_attr)
3184 goto fail;
3185 if (nla_put(skb,
3186 NL80211_ATTR_SSID,
3187 hdd_sta_ctx->conn_info.SSID.SSID.length,
3188 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3189 hdd_err("put fail");
3190 goto fail;
3191 }
3192 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3193 goto fail;
3194 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3195 goto fail;
3196 nla_nest_end(skb, nla_attr);
3197 return 0;
3198fail:
3199 return -EINVAL;
3200}
3201
3202/**
3203 * hdd_add_ap_standard_info() - add ap info attribute
3204 * @skb: pointer to sk buff
3205 * @hdd_sta_ctx: pointer to hdd station context
3206 * @idx: attribute index
3207 *
3208 * Return: Success(0) or reason code for failure
3209 */
3210static int32_t
3211hdd_add_ap_standard_info(struct sk_buff *skb,
3212 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3213{
3214 struct nlattr *nla_attr;
3215
3216 nla_attr = nla_nest_start(skb, idx);
3217 if (!nla_attr)
3218 goto fail;
3219 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3220 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3221 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3222 &hdd_sta_ctx->conn_info.vht_caps)) {
3223 hdd_err("put fail");
3224 goto fail;
3225 }
3226 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3227 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3228 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3229 &hdd_sta_ctx->conn_info.ht_caps)) {
3230 hdd_err("put fail");
3231 goto fail;
3232 }
3233 nla_nest_end(skb, nla_attr);
3234 return 0;
3235fail:
3236 return -EINVAL;
3237}
3238
3239/**
3240 * hdd_get_station_info() - send BSS information to supplicant
3241 * @hdd_ctx: pointer to hdd context
3242 * @adapter: pointer to adapter
3243 *
3244 * Return: 0 if success else error status
3245 */
3246static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3247 hdd_adapter_t *adapter)
3248{
3249 struct sk_buff *skb = NULL;
3250 uint8_t *tmp_hs20 = NULL;
3251 uint32_t nl_buf_len;
3252 hdd_station_ctx_t *hdd_sta_ctx;
3253
3254 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3255
3256 nl_buf_len = NLMSG_HDRLEN;
3257 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3258 sizeof(hdd_sta_ctx->conn_info.freq) +
3259 sizeof(hdd_sta_ctx->conn_info.noise) +
3260 sizeof(hdd_sta_ctx->conn_info.signal) +
3261 (sizeof(uint32_t) * 2) +
3262 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3263 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3264 sizeof(hdd_sta_ctx->conn_info.authType) +
3265 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3266 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3267 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3268 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3269 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3270 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3271 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3272 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3273 1);
3274 }
3275 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3276 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3277 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3278 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3279
3280
3281 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3282 if (!skb) {
3283 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3284 return -ENOMEM;
3285 }
3286
3287 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3288 LINK_INFO_STANDARD_NL80211_ATTR)) {
3289 hdd_err("put fail");
3290 goto fail;
3291 }
3292 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3293 AP_INFO_STANDARD_NL80211_ATTR)) {
3294 hdd_err("put fail");
3295 goto fail;
3296 }
3297 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3298 hdd_sta_ctx->conn_info.roam_count) ||
3299 nla_put_u32(skb, INFO_AKM,
3300 hdd_convert_auth_type(
3301 hdd_sta_ctx->conn_info.authType)) ||
3302 nla_put_u32(skb, WLAN802_11_MODE,
3303 hdd_convert_dot11mode(
3304 hdd_sta_ctx->conn_info.dot11Mode))) {
3305 hdd_err("put fail");
3306 goto fail;
3307 }
3308 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3309 if (nla_put(skb, HT_OPERATION,
3310 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3311 &hdd_sta_ctx->conn_info.ht_operation)) {
3312 hdd_err("put fail");
3313 goto fail;
3314 }
3315 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3316 if (nla_put(skb, VHT_OPERATION,
3317 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3318 &hdd_sta_ctx->conn_info.vht_operation)) {
3319 hdd_err("put fail");
3320 goto fail;
3321 }
3322 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3323 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3324 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3325 tmp_hs20 + 1)) {
3326 hdd_err("put fail");
3327 goto fail;
3328 }
3329
3330 return cfg80211_vendor_cmd_reply(skb);
3331fail:
3332 if (skb)
3333 kfree_skb(skb);
3334 return -EINVAL;
3335}
3336
3337/**
3338 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3339 * @wiphy: corestack handler
3340 * @wdev: wireless device
3341 * @data: data
3342 * @data_len: data length
3343 *
3344 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3345 * Validate cmd attributes and send the station info to upper layers.
3346 *
3347 * Return: Success(0) or reason code for failure
3348 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303349static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303350__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3351 struct wireless_dev *wdev,
3352 const void *data,
3353 int data_len)
3354{
3355 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3356 struct net_device *dev = wdev->netdev;
3357 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3358 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3359 int32_t status;
3360
3361 ENTER_DEV(dev);
3362 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3363 hdd_err("Command not allowed in FTM mode");
3364 status = -EPERM;
3365 goto out;
3366 }
3367
3368 status = wlan_hdd_validate_context(hdd_ctx);
3369 if (0 != status)
3370 goto out;
3371
3372
3373 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3374 data, data_len, NULL);
3375 if (status) {
3376 hdd_err("Invalid ATTR");
3377 goto out;
3378 }
3379
3380 /* Parse and fetch Command Type*/
3381 if (tb[STATION_INFO]) {
3382 status = hdd_get_station_info(hdd_ctx, adapter);
3383 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3384 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3385 } else {
3386 hdd_err("get station info cmd type failed");
3387 status = -EINVAL;
3388 goto out;
3389 }
3390 EXIT();
3391out:
3392 return status;
3393}
3394
3395/**
3396 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3397 * @wiphy: corestack handler
3398 * @wdev: wireless device
3399 * @data: data
3400 * @data_len: data length
3401 *
3402 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3403 * Validate cmd attributes and send the station info to upper layers.
3404 *
3405 * Return: Success(0) or reason code for failure
3406 */
3407static int32_t
3408hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3409 struct wireless_dev *wdev,
3410 const void *data,
3411 int data_len)
3412{
3413 int ret;
3414
3415 cds_ssr_protect(__func__);
3416 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3417 cds_ssr_unprotect(__func__);
3418
3419 return ret;
3420}
3421
3422/*
3423 * undef short names defined for get station command
3424 * used by __wlan_hdd_cfg80211_get_station_cmd()
3425 */
3426#undef STATION_INVALID
3427#undef STATION_INFO
3428#undef STATION_ASSOC_FAIL_REASON
3429#undef STATION_MAX
3430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003431#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3432/**
3433 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3434 * @wiphy: pointer to wireless wiphy structure.
3435 * @wdev: pointer to wireless_dev structure.
3436 * @data: Pointer to the Key data
3437 * @data_len:Length of the data passed
3438 *
3439 * This is called when wlan driver needs to save the keys received via
3440 * vendor specific command.
3441 *
3442 * Return: Return the Success or Failure code.
3443 */
3444static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3445 struct wireless_dev *wdev,
3446 const void *data, int data_len)
3447{
3448 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3449 struct net_device *dev = wdev->netdev;
3450 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3451 hdd_context_t *hdd_ctx_ptr;
3452 int status;
3453
Jeff Johnson1f61b612016-02-12 16:28:33 -08003454 ENTER_DEV(dev);
3455
Anurag Chouhan6d760662016-02-20 16:05:43 +05303456 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457 hdd_err("Command not allowed in FTM mode");
3458 return -EPERM;
3459 }
3460
3461 if ((data == NULL) || (data_len == 0) ||
3462 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003463 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003464 return -EINVAL;
3465 }
3466
3467 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3468 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003469 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 return -EINVAL;
3471 }
3472
3473 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303474 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3477 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003478 true,
3479 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303480 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3481 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3483 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3484 return 0;
3485}
3486
3487/**
3488 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3489 * @wiphy: pointer to wireless wiphy structure.
3490 * @wdev: pointer to wireless_dev structure.
3491 * @data: Pointer to the Key data
3492 * @data_len:Length of the data passed
3493 *
3494 * This is called when wlan driver needs to save the keys received via
3495 * vendor specific command.
3496 *
3497 * Return: Return the Success or Failure code.
3498 */
3499static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3500 struct wireless_dev *wdev,
3501 const void *data, int data_len)
3502{
3503 int ret;
3504
3505 cds_ssr_protect(__func__);
3506 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3507 cds_ssr_unprotect(__func__);
3508
3509 return ret;
3510}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003511#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512
3513static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3514 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3515 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3516 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003517 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518};
3519
3520/**
3521 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3522 * @wiphy: pointer to wireless wiphy structure.
3523 * @wdev: pointer to wireless_dev structure.
3524 * @data: Pointer to the data to be passed via vendor interface
3525 * @data_len:Length of the data to be passed
3526 *
3527 * This is called when wlan driver needs to send wifi driver related info
3528 * (driver/fw version) to the user space application upon request.
3529 *
3530 * Return: Return the Success or Failure code.
3531 */
3532static int
3533__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3534 struct wireless_dev *wdev,
3535 const void *data, int data_len)
3536{
3537 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3538 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003539 tSirVersionString driver_version;
3540 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003543 struct sk_buff *reply_skb;
3544 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545
Jeff Johnson1f61b612016-02-12 16:28:33 -08003546 ENTER_DEV(wdev->netdev);
3547
Anurag Chouhan6d760662016-02-20 16:05:43 +05303548 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549 hdd_err("Command not allowed in FTM mode");
3550 return -EPERM;
3551 }
3552
3553 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303554 if (status)
3555 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003556
3557 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3558 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003559 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003560 return -EINVAL;
3561 }
3562
3563 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003564 hdd_err("Rcvd req for Driver version");
3565 strlcpy(driver_version, QWLAN_VERSIONSTR,
3566 sizeof(driver_version));
3567 skb_len += strlen(driver_version) + 1;
3568 count++;
3569 }
3570
3571 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3572 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3574 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003575 snprintf(firmware_version, sizeof(firmware_version),
3576 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3577 skb_len += strlen(firmware_version) + 1;
3578 count++;
3579 }
3580
3581 if (count == 0) {
3582 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003583 return -EINVAL;
3584 }
3585
Ryan Hsu7ac88852016-04-28 10:20:34 -07003586 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3587 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3588
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003590 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591 return -ENOMEM;
3592 }
3593
Ryan Hsu7ac88852016-04-28 10:20:34 -07003594 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3595 if (nla_put_string(reply_skb,
3596 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3597 driver_version))
3598 goto error_nla_fail;
3599 }
3600
3601 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3602 if (nla_put_string(reply_skb,
3603 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3604 firmware_version))
3605 goto error_nla_fail;
3606 }
3607
3608 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3609 if (nla_put_u32(reply_skb,
3610 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3611 hdd_ctx->radio_index))
3612 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 }
3614
3615 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003616
3617error_nla_fail:
3618 hdd_err("nla put fail");
3619 kfree_skb(reply_skb);
3620 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621}
3622
3623/**
3624 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3625 * @wiphy: pointer to wireless wiphy structure.
3626 * @wdev: pointer to wireless_dev structure.
3627 * @data: Pointer to the data to be passed via vendor interface
3628 * @data_len:Length of the data to be passed
3629 *
3630 * This is called when wlan driver needs to send wifi driver related info
3631 * (driver/fw version) to the user space application upon request.
3632 *
3633 * Return: Return the Success or Failure code.
3634 */
3635static int
3636wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3637 struct wireless_dev *wdev,
3638 const void *data, int data_len)
3639{
3640 int ret;
3641
3642 cds_ssr_protect(__func__);
3643 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3644 cds_ssr_unprotect(__func__);
3645
3646 return ret;
3647}
3648
3649/**
3650 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3651 * @wiphy: pointer to wireless wiphy structure.
3652 * @wdev: pointer to wireless_dev structure.
3653 * @data: Pointer to the data to be passed via vendor interface
3654 * @data_len:Length of the data to be passed
3655 *
3656 * This is called by userspace to know the supported logger features
3657 *
3658 * Return: Return the Success or Failure code.
3659 */
3660static int
3661__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3662 struct wireless_dev *wdev,
3663 const void *data, int data_len)
3664{
3665 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3666 int status;
3667 uint32_t features;
3668 struct sk_buff *reply_skb = NULL;
3669
Jeff Johnson1f61b612016-02-12 16:28:33 -08003670 ENTER_DEV(wdev->netdev);
3671
Anurag Chouhan6d760662016-02-20 16:05:43 +05303672 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 hdd_err("Command not allowed in FTM mode");
3674 return -EPERM;
3675 }
3676
3677 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303678 if (status)
3679 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680
3681 features = 0;
3682
3683 if (hdd_is_memdump_supported())
3684 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3685 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3686 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3687 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3688
3689 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3690 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3691 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003692 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693 return -ENOMEM;
3694 }
3695
Jeff Johnson020db452016-06-29 14:37:26 -07003696 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3698 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003699 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003700 kfree_skb(reply_skb);
3701 return -EINVAL;
3702 }
3703
3704 return cfg80211_vendor_cmd_reply(reply_skb);
3705}
3706
3707/**
3708 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3709 * @wiphy: pointer to wireless wiphy structure.
3710 * @wdev: pointer to wireless_dev structure.
3711 * @data: Pointer to the data to be passed via vendor interface
3712 * @data_len:Length of the data to be passed
3713 *
3714 * This is called by userspace to know the supported logger features
3715 *
3716 * Return: Return the Success or Failure code.
3717 */
3718static int
3719wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3720 struct wireless_dev *wdev,
3721 const void *data, int data_len)
3722{
3723 int ret;
3724
3725 cds_ssr_protect(__func__);
3726 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3727 data, data_len);
3728 cds_ssr_unprotect(__func__);
3729
3730 return ret;
3731}
3732
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003733#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734/**
3735 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3736 * @hdd_ctx_ptr: pointer to HDD Context.
3737 * @bssid: pointer to bssid of roamed AP.
3738 * @req_rsn_ie: Pointer to request RSN IE
3739 * @req_rsn_len: Length of the request RSN IE
3740 * @rsp_rsn_ie: Pointer to response RSN IE
3741 * @rsp_rsn_len: Length of the response RSN IE
3742 * @roam_info_ptr: Pointer to the roaming related information
3743 *
3744 * This is called when wlan driver needs to send the roaming and
3745 * authorization information after roaming.
3746 *
3747 * The information that would be sent is the request RSN IE, response
3748 * RSN IE and BSSID of the newly roamed AP.
3749 *
3750 * If the Authorized status is authenticated, then additional parameters
3751 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3752 * supplicant.
3753 *
3754 * The supplicant upon receiving this event would ignore the legacy
3755 * cfg80211_roamed call and use the entire information from this event.
3756 * The cfg80211_roamed should still co-exist since the kernel will
3757 * make use of the parameters even if the supplicant ignores it.
3758 *
3759 * Return: Return the Success or Failure code.
3760 */
3761int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3762 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3763 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3764{
3765 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003766 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767 ENTER();
3768
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303769 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003772 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003773 !roam_info_ptr->roamSynchInProgress)
3774 return 0;
3775
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3777 NULL,
3778 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3779 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3780 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003781 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3783 GFP_KERNEL);
3784
3785 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003786 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 return -EINVAL;
3788 }
3789
3790 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3791 ETH_ALEN, bssid) ||
3792 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3793 req_rsn_len, req_rsn_ie) ||
3794 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3795 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003796 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797 goto nla_put_failure;
3798 }
Jeff Johnson020db452016-06-29 14:37:26 -07003799 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800 if (roam_info_ptr->synchAuthStatus ==
3801 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003802 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003803 if (nla_put_u8(skb,
3804 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3805 hdd_err("nla put fail");
3806 goto nla_put_failure;
3807 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003808 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3809 /* if FT or CCKM connection: dont send replay counter */
3810 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3811 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3812 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3813 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3814 nla_put(skb,
3815 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3816 SIR_REPLAY_CTR_LEN,
3817 roam_info_ptr->replay_ctr)) {
3818 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003819 hdd_err("failed to send replay counter.");
3820 goto nla_put_failure;
3821 }
3822 if (nla_put(skb,
3823 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3824 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3825 nla_put(skb,
3826 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3827 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3828 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829 goto nla_put_failure;
3830 }
3831 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003832 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003833 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3834 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003835 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836 goto nla_put_failure;
3837 }
3838 }
3839
Jeff Johnson020db452016-06-29 14:37:26 -07003840 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003841 roam_info_ptr->subnet_change_status);
3842
3843 /*
3844 * Add subnet change status if subnet has changed
3845 * 0 = unchanged
3846 * 1 = changed
3847 * 2 = unknown
3848 */
3849 if (roam_info_ptr->subnet_change_status) {
3850 if (nla_put_u8(skb,
3851 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3852 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003853 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003854 goto nla_put_failure;
3855 }
3856 }
3857
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858 cfg80211_vendor_event(skb, GFP_KERNEL);
3859 return 0;
3860
3861nla_put_failure:
3862 kfree_skb(skb);
3863 return -EINVAL;
3864}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003865#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866
3867static const struct nla_policy
3868wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3869
3870 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3871 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3872 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303873 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303874 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3875 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876};
3877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303879 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3880 *
3881 * @adapter: Pointer to HDD adapter
3882 * @ie_data: Pointer to Scan IEs buffer
3883 * @ie_len: Length of Scan IEs
3884 *
3885 * Return: 0 on success; error number otherwise
3886 */
3887static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3888 uint8_t *ie_data, uint8_t ie_len)
3889{
3890 hdd_scaninfo_t *scan_info = NULL;
3891 scan_info = &adapter->scan_info;
3892
3893 if (scan_info->default_scan_ies) {
3894 qdf_mem_free(scan_info->default_scan_ies);
3895 scan_info->default_scan_ies = NULL;
3896 }
3897
3898 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3899 if (!scan_info->default_scan_ies)
3900 return -ENOMEM;
3901
3902 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3903 scan_info->default_scan_ies_len = ie_len;
3904 return 0;
3905}
3906
3907/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3909 * vendor command
3910 *
3911 * @wiphy: wiphy device pointer
3912 * @wdev: wireless device pointer
3913 * @data: Vendor command data buffer
3914 * @data_len: Buffer length
3915 *
3916 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3917 *
3918 * Return: Error code.
3919 */
3920static int
3921__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3922 struct wireless_dev *wdev,
3923 const void *data,
3924 int data_len)
3925{
3926 struct net_device *dev = wdev->netdev;
3927 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3928 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3929 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3930 int ret_val = 0;
3931 u32 modulated_dtim;
3932 u16 stats_avg_factor;
3933 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303934 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003935 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003936 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303937 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303938 int attr_len;
3939 int access_policy = 0;
3940 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3941 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303942 uint16_t scan_ie_len = 0;
3943 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303944 struct sir_set_tx_rx_aggregation_size request;
3945 QDF_STATUS qdf_status;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303946
Jeff Johnson1f61b612016-02-12 16:28:33 -08003947 ENTER_DEV(dev);
3948
Anurag Chouhan6d760662016-02-20 16:05:43 +05303949 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 hdd_err("Command not allowed in FTM mode");
3951 return -EPERM;
3952 }
3953
3954 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303955 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957
3958 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3959 data, data_len,
3960 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003961 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962 return -EINVAL;
3963 }
3964
Krunal Sonie3531942016-04-12 17:43:53 -07003965 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3966 ftm_capab = nla_get_u32(tb[
3967 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3968 hdd_ctx->config->fine_time_meas_cap =
3969 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3970 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303971 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003972 hdd_ctx->config->fine_time_meas_cap);
3973 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3974 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3975 hdd_ctx->config->fine_time_meas_cap);
3976 }
3977
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3979 modulated_dtim = nla_get_u32(
3980 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3981
3982 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3983 adapter->sessionId,
3984 modulated_dtim);
3985
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303986 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003987 ret_val = -EPERM;
3988 }
3989
Kapil Gupta6213c012016-09-02 19:39:09 +05303990 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
3991 qpower = nla_get_u8(
3992 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
3993 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
3994 ret_val = -EINVAL;
3995 }
3996
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003997 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3998 stats_avg_factor = nla_get_u16(
3999 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4000 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4001 adapter->sessionId,
4002 stats_avg_factor);
4003
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304004 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004005 ret_val = -EPERM;
4006 }
4007
4008
4009 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4010 guard_time = nla_get_u32(
4011 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4012 status = sme_configure_guard_time(hdd_ctx->hHal,
4013 adapter->sessionId,
4014 guard_time);
4015
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304016 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 ret_val = -EPERM;
4018 }
4019
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304020 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4021 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4022 attr_len = nla_len(
4023 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4024 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4025 hdd_info("Invalid value. attr_len %d",
4026 attr_len);
4027 return -EINVAL;
4028 }
4029
4030 nla_memcpy(&vendor_ie,
4031 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4032 attr_len);
4033 vendor_ie_present = true;
4034 hdd_info("Access policy vendor ie present.attr_len %d",
4035 attr_len);
4036 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4037 &vendor_ie[0], attr_len);
4038 }
4039
4040 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4041 access_policy = (int) nla_get_u32(
4042 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4043 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4044 (access_policy >
4045 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4046 hdd_info("Invalid value. access_policy %d",
4047 access_policy);
4048 return -EINVAL;
4049 }
4050 access_policy_present = true;
4051 hdd_info("Access policy present. access_policy %d",
4052 access_policy);
4053 }
4054
4055 if (vendor_ie_present && access_policy_present) {
4056 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4057 access_policy =
4058 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
4059 } else {
4060 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
4061 }
4062
4063 hdd_info("calling sme_update_access_policy_vendor_ie");
4064 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4065 adapter->sessionId, &vendor_ie[0],
4066 access_policy);
4067 if (QDF_STATUS_SUCCESS != status) {
4068 hdd_info("Failed to set vendor ie and access policy.");
4069 return -EINVAL;
4070 }
4071 }
4072
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304073 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4074 set_value = nla_get_u8(
4075 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4076 hdd_info("set_value: %d", set_value);
4077 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4078 }
4079
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304080 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4081 scan_ie_len = nla_len(
4082 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4083 hdd_info("Received default scan IE of len %d session %d device mode %d",
4084 scan_ie_len, adapter->sessionId,
4085 adapter->device_mode);
4086 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4087 scan_ie = (uint8_t *) nla_data(tb
4088 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304089
4090 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4091 scan_ie_len))
4092 hdd_err("Failed to save default scan IEs");
4093
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304094 if (adapter->device_mode == QDF_STA_MODE) {
4095 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4096 adapter->sessionId, scan_ie,
4097 scan_ie_len);
4098 if (QDF_STATUS_SUCCESS != status)
4099 ret_val = -EPERM;
4100 }
4101 } else
4102 ret_val = -EPERM;
4103 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304104
4105 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4106 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4107 /* if one is specified, both must be specified */
4108 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4109 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4110 hdd_err("Both TX and RX MPDU Aggregation required");
4111 return -EINVAL;
4112 }
4113
4114 request.tx_aggregation_size = nla_get_u8(
4115 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4116 request.rx_aggregation_size = nla_get_u8(
4117 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4118 request.vdev_id = adapter->sessionId;
4119
4120 if (request.tx_aggregation_size >=
4121 CFG_TX_AGGREGATION_SIZE_MIN &&
4122 request.tx_aggregation_size <=
4123 CFG_TX_AGGREGATION_SIZE_MAX &&
4124 request.rx_aggregation_size >=
4125 CFG_RX_AGGREGATION_SIZE_MIN &&
4126 request.rx_aggregation_size <=
4127 CFG_RX_AGGREGATION_SIZE_MAX) {
4128 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4129 if (qdf_status != QDF_STATUS_SUCCESS) {
4130 hdd_err("failed to set aggr sizes err %d",
4131 qdf_status);
4132 ret_val = -EPERM;
4133 }
4134 } else {
4135 hdd_err("TX %d RX %d MPDU aggr size not in range",
4136 request.tx_aggregation_size,
4137 request.rx_aggregation_size);
4138 ret_val = -EINVAL;
4139 }
4140 }
4141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 return ret_val;
4143}
4144
4145/**
4146 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4147 * vendor command
4148 *
4149 * @wiphy: wiphy device pointer
4150 * @wdev: wireless device pointer
4151 * @data: Vendor command data buffer
4152 * @data_len: Buffer length
4153 *
4154 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4155 *
4156 * Return: EOK or other error codes.
4157 */
4158static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4159 struct wireless_dev *wdev,
4160 const void *data,
4161 int data_len)
4162{
4163 int ret;
4164
4165 cds_ssr_protect(__func__);
4166 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4167 data, data_len);
4168 cds_ssr_unprotect(__func__);
4169
4170 return ret;
4171}
4172
4173static const struct
4174nla_policy
4175qca_wlan_vendor_wifi_logger_start_policy
4176[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4177 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4178 = {.type = NLA_U32 },
4179 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4180 = {.type = NLA_U32 },
4181 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4182 = {.type = NLA_U32 },
4183};
4184
4185/**
4186 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4187 * or disable the collection of packet statistics from the firmware
4188 * @wiphy: WIPHY structure pointer
4189 * @wdev: Wireless device structure pointer
4190 * @data: Pointer to the data received
4191 * @data_len: Length of the data received
4192 *
4193 * This function enables or disables the collection of packet statistics from
4194 * the firmware
4195 *
4196 * Return: 0 on success and errno on failure
4197 */
4198static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4199 struct wireless_dev *wdev,
4200 const void *data,
4201 int data_len)
4202{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304203 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4205 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4206 struct sir_wifi_start_log start_log;
4207
Jeff Johnson1f61b612016-02-12 16:28:33 -08004208 ENTER_DEV(wdev->netdev);
4209
Anurag Chouhan6d760662016-02-20 16:05:43 +05304210 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 hdd_err("Command not allowed in FTM mode");
4212 return -EPERM;
4213 }
4214
4215 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304216 if (status)
4217 return status;
4218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219
4220 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4221 data, data_len,
4222 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004223 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 return -EINVAL;
4225 }
4226
4227 /* Parse and fetch ring id */
4228 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004229 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004230 return -EINVAL;
4231 }
4232 start_log.ring_id = nla_get_u32(
4233 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004234 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235
4236 /* Parse and fetch verbose level */
4237 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004238 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004239 return -EINVAL;
4240 }
4241 start_log.verbose_level = nla_get_u32(
4242 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004243 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004244
4245 /* Parse and fetch flag */
4246 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004247 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 return -EINVAL;
4249 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304250 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304252 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253
4254 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4255
4256 if (start_log.ring_id == RING_ID_WAKELOCK) {
4257 /* Start/stop wakelock events */
4258 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4259 cds_set_wakelock_logging(true);
4260 else
4261 cds_set_wakelock_logging(false);
4262 return 0;
4263 }
4264
4265 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304266 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004267 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004268 status);
4269 return -EINVAL;
4270 }
4271 return 0;
4272}
4273
4274/**
4275 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4276 * or disable the collection of packet statistics from the firmware
4277 * @wiphy: WIPHY structure pointer
4278 * @wdev: Wireless device structure pointer
4279 * @data: Pointer to the data received
4280 * @data_len: Length of the data received
4281 *
4282 * This function is used to enable or disable the collection of packet
4283 * statistics from the firmware
4284 *
4285 * Return: 0 on success and errno on failure
4286 */
4287static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4288 struct wireless_dev *wdev,
4289 const void *data,
4290 int data_len)
4291{
4292 int ret = 0;
4293
4294 cds_ssr_protect(__func__);
4295 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4296 wdev, data, data_len);
4297 cds_ssr_unprotect(__func__);
4298
4299 return ret;
4300}
4301
4302static const struct
4303nla_policy
4304qca_wlan_vendor_wifi_logger_get_ring_data_policy
4305[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4306 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4307 = {.type = NLA_U32 },
4308};
4309
4310/**
4311 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4312 * @wiphy: WIPHY structure pointer
4313 * @wdev: Wireless device structure pointer
4314 * @data: Pointer to the data received
4315 * @data_len: Length of the data received
4316 *
4317 * This function is used to flush or retrieve the per packet statistics from
4318 * the driver
4319 *
4320 * Return: 0 on success and errno on failure
4321 */
4322static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4323 struct wireless_dev *wdev,
4324 const void *data,
4325 int data_len)
4326{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304327 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328 uint32_t ring_id;
4329 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4330 struct nlattr *tb
4331 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4332
Jeff Johnson1f61b612016-02-12 16:28:33 -08004333 ENTER_DEV(wdev->netdev);
4334
Anurag Chouhan6d760662016-02-20 16:05:43 +05304335 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 hdd_err("Command not allowed in FTM mode");
4337 return -EPERM;
4338 }
4339
4340 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304341 if (status)
4342 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343
4344 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4345 data, data_len,
4346 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004347 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 return -EINVAL;
4349 }
4350
4351 /* Parse and fetch ring id */
4352 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004353 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 return -EINVAL;
4355 }
4356
4357 ring_id = nla_get_u32(
4358 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4359
4360 if (ring_id == RING_ID_PER_PACKET_STATS) {
4361 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004362 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304363 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4364 /*
4365 * As part of DRIVER ring ID, flush both driver and fw logs.
4366 * For other Ring ID's driver doesn't have any rings to flush
4367 */
4368 hdd_notice("Bug report triggered by framework");
4369
4370 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4371 WLAN_LOG_INDICATOR_FRAMEWORK,
4372 WLAN_LOG_REASON_CODE_UNUSED,
4373 true, false);
4374 if (QDF_STATUS_SUCCESS != status) {
4375 hdd_err("Failed to trigger bug report");
4376 return -EINVAL;
4377 }
4378 } else {
4379 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4380 WLAN_LOG_INDICATOR_FRAMEWORK,
4381 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 return 0;
4384}
4385
4386/**
4387 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4388 * @wiphy: WIPHY structure pointer
4389 * @wdev: Wireless device structure pointer
4390 * @data: Pointer to the data received
4391 * @data_len: Length of the data received
4392 *
4393 * This function is used to flush or retrieve the per packet statistics from
4394 * the driver
4395 *
4396 * Return: 0 on success and errno on failure
4397 */
4398static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4399 struct wireless_dev *wdev,
4400 const void *data,
4401 int data_len)
4402{
4403 int ret = 0;
4404
4405 cds_ssr_protect(__func__);
4406 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4407 wdev, data, data_len);
4408 cds_ssr_unprotect(__func__);
4409
4410 return ret;
4411}
4412
4413#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4414/**
4415 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4416 * @hdd_ctx: HDD context
4417 * @request_id: [input] request id
4418 * @pattern_id: [output] pattern id
4419 *
4420 * This function loops through request id to pattern id array
4421 * if the slot is available, store the request id and return pattern id
4422 * if entry exists, return the pattern id
4423 *
4424 * Return: 0 on success and errno on failure
4425 */
4426static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4427 uint32_t request_id,
4428 uint8_t *pattern_id)
4429{
4430 uint32_t i;
4431
4432 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4433 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4434 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4435 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4436 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4437 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4438 return 0;
4439 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4440 request_id) {
4441 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4442 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4443 return 0;
4444 }
4445 }
4446 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4447 return -EINVAL;
4448}
4449
4450/**
4451 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4452 * @hdd_ctx: HDD context
4453 * @request_id: [input] request id
4454 * @pattern_id: [output] pattern id
4455 *
4456 * This function loops through request id to pattern id array
4457 * reset request id to 0 (slot available again) and
4458 * return pattern id
4459 *
4460 * Return: 0 on success and errno on failure
4461 */
4462static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4463 uint32_t request_id,
4464 uint8_t *pattern_id)
4465{
4466 uint32_t i;
4467
4468 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4469 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4470 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4471 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4472 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4473 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4474 return 0;
4475 }
4476 }
4477 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4478 return -EINVAL;
4479}
4480
4481
4482/*
4483 * define short names for the global vendor params
4484 * used by __wlan_hdd_cfg80211_offloaded_packets()
4485 */
4486#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4487#define PARAM_REQUEST_ID \
4488 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4489#define PARAM_CONTROL \
4490 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4491#define PARAM_IP_PACKET \
4492 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4493#define PARAM_SRC_MAC_ADDR \
4494 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4495#define PARAM_DST_MAC_ADDR \
4496 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4497#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4498
4499/**
4500 * wlan_hdd_add_tx_ptrn() - add tx pattern
4501 * @adapter: adapter pointer
4502 * @hdd_ctx: hdd context
4503 * @tb: nl attributes
4504 *
4505 * This function reads the NL attributes and forms a AddTxPtrn message
4506 * posts it to SME.
4507 *
4508 */
4509static int
4510wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4511 struct nlattr **tb)
4512{
4513 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304514 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004515 uint32_t request_id, ret, len;
4516 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304517 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004518 uint16_t eth_type = htons(ETH_P_IP);
4519
4520 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004521 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 return -ENOTSUPP;
4523 }
4524
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304525 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004527 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 return -ENOMEM;
4529 }
4530
4531 /* Parse and fetch request Id */
4532 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004533 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004534 goto fail;
4535 }
4536
4537 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4538 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004539 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540 return -EINVAL;
4541 }
Jeff Johnson77848112016-06-29 14:52:06 -07004542 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543
4544 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004545 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 goto fail;
4547 }
4548 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004549 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004550 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004551 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 goto fail;
4553 }
4554
4555 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004556 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 goto fail;
4558 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004559 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304560 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004561 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004562 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563
Anurag Chouhanc5548422016-02-24 18:33:27 +05304564 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004565 &adapter->macAddressCurrent)) {
4566 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004567 goto fail;
4568 }
4569
4570 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004571 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572 goto fail;
4573 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304574 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004575 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 MAC_ADDR_ARRAY(dst_addr.bytes));
4577
4578 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004579 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 goto fail;
4581 }
4582 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004583 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584
4585 if (add_req->ucPtrnSize < 0 ||
4586 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4587 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004588 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 add_req->ucPtrnSize);
4590 goto fail;
4591 }
4592
4593 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304594 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304595 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304596 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304597 QDF_MAC_ADDR_SIZE);
4598 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304599 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004600 len += 2;
4601
4602 /*
4603 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4604 * ------------------------------------------------------------
4605 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4606 * ------------------------------------------------------------
4607 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304608 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 nla_data(tb[PARAM_IP_PACKET]),
4610 add_req->ucPtrnSize);
4611 add_req->ucPtrnSize += len;
4612
4613 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4614 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004615 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 goto fail;
4617 }
4618 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004619 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620
4621 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304622 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004623 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004624 goto fail;
4625 }
4626
4627 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304628 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004629 return 0;
4630
4631fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304632 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633 return -EINVAL;
4634}
4635
4636/**
4637 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4638 * @adapter: adapter pointer
4639 * @hdd_ctx: hdd context
4640 * @tb: nl attributes
4641 *
4642 * This function reads the NL attributes and forms a DelTxPtrn message
4643 * posts it to SME.
4644 *
4645 */
4646static int
4647wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4648 struct nlattr **tb)
4649{
4650 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304651 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 uint32_t request_id, ret;
4653 uint8_t pattern_id = 0;
4654
4655 /* Parse and fetch request Id */
4656 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004657 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 return -EINVAL;
4659 }
4660 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4661 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004662 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 return -EINVAL;
4664 }
4665
4666 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4667 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004668 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 return -EINVAL;
4670 }
4671
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304672 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004674 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 return -ENOMEM;
4676 }
4677
Anurag Chouhanc5548422016-02-24 18:33:27 +05304678 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004679 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004681 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682 request_id, del_req->ucPtrnId);
4683
4684 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304685 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004686 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004687 goto fail;
4688 }
4689
4690 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304691 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 return 0;
4693
4694fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304695 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 return -EINVAL;
4697}
4698
4699
4700/**
4701 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4702 * @wiphy: Pointer to wireless phy
4703 * @wdev: Pointer to wireless device
4704 * @data: Pointer to data
4705 * @data_len: Data length
4706 *
4707 * Return: 0 on success, negative errno on failure
4708 */
4709static int
4710__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4711 struct wireless_dev *wdev,
4712 const void *data,
4713 int data_len)
4714{
4715 struct net_device *dev = wdev->netdev;
4716 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4717 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4718 struct nlattr *tb[PARAM_MAX + 1];
4719 uint8_t control;
4720 int ret;
4721 static const struct nla_policy policy[PARAM_MAX + 1] = {
4722 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4723 [PARAM_CONTROL] = { .type = NLA_U32 },
4724 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304725 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304727 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004728 [PARAM_PERIOD] = { .type = NLA_U32 },
4729 };
4730
Jeff Johnson1f61b612016-02-12 16:28:33 -08004731 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732
Anurag Chouhan6d760662016-02-20 16:05:43 +05304733 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004734 hdd_err("Command not allowed in FTM mode");
4735 return -EPERM;
4736 }
4737
4738 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304739 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004740 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741
4742 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004743 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004744 return -ENOTSUPP;
4745 }
4746
4747 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004748 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749 return -EINVAL;
4750 }
4751
4752 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004753 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 return -EINVAL;
4755 }
4756 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004757 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758
4759 if (control == WLAN_START_OFFLOADED_PACKETS)
4760 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4761 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4762 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4763 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004764 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004765 return -EINVAL;
4766 }
4767}
4768
4769/*
4770 * done with short names for the global vendor params
4771 * used by __wlan_hdd_cfg80211_offloaded_packets()
4772 */
4773#undef PARAM_MAX
4774#undef PARAM_REQUEST_ID
4775#undef PARAM_CONTROL
4776#undef PARAM_IP_PACKET
4777#undef PARAM_SRC_MAC_ADDR
4778#undef PARAM_DST_MAC_ADDR
4779#undef PARAM_PERIOD
4780
4781/**
4782 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4783 * @wiphy: wiphy structure pointer
4784 * @wdev: Wireless device structure pointer
4785 * @data: Pointer to the data received
4786 * @data_len: Length of @data
4787 *
4788 * Return: 0 on success; errno on failure
4789 */
4790static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4791 struct wireless_dev *wdev,
4792 const void *data,
4793 int data_len)
4794{
4795 int ret = 0;
4796
4797 cds_ssr_protect(__func__);
4798 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4799 wdev, data, data_len);
4800 cds_ssr_unprotect(__func__);
4801
4802 return ret;
4803}
4804#endif
4805
4806/*
4807 * define short names for the global vendor params
4808 * used by __wlan_hdd_cfg80211_monitor_rssi()
4809 */
4810#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4811#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4812#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4813#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4814#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4815
4816/**
4817 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4818 * @wiphy: Pointer to wireless phy
4819 * @wdev: Pointer to wireless device
4820 * @data: Pointer to data
4821 * @data_len: Data length
4822 *
4823 * Return: 0 on success, negative errno on failure
4824 */
4825static int
4826__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4827 struct wireless_dev *wdev,
4828 const void *data,
4829 int data_len)
4830{
4831 struct net_device *dev = wdev->netdev;
4832 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4833 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4834 struct nlattr *tb[PARAM_MAX + 1];
4835 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304836 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 int ret;
4838 uint32_t control;
4839 static const struct nla_policy policy[PARAM_MAX + 1] = {
4840 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4841 [PARAM_CONTROL] = { .type = NLA_U32 },
4842 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4843 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4844 };
4845
Jeff Johnson1f61b612016-02-12 16:28:33 -08004846 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004847
4848 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304849 if (ret)
4850 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851
4852 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004853 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 return -ENOTSUPP;
4855 }
4856
4857 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004858 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 return -EINVAL;
4860 }
4861
4862 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004863 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004864 return -EINVAL;
4865 }
4866
4867 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004868 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004869 return -EINVAL;
4870 }
4871
4872 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4873 req.session_id = adapter->sessionId;
4874 control = nla_get_u32(tb[PARAM_CONTROL]);
4875
4876 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4877 req.control = true;
4878 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004879 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 return -EINVAL;
4881 }
4882
4883 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004884 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885 return -EINVAL;
4886 }
4887
4888 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4889 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4890
4891 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004892 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004893 req.min_rssi, req.max_rssi);
4894 return -EINVAL;
4895 }
Jeff Johnson77848112016-06-29 14:52:06 -07004896 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004897 req.min_rssi, req.max_rssi);
4898
4899 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4900 req.control = false;
4901 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004902 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 return -EINVAL;
4904 }
Jeff Johnson77848112016-06-29 14:52:06 -07004905 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906 req.request_id, req.session_id, req.control);
4907
4908 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304909 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913
4914 return 0;
4915}
4916
4917/*
4918 * done with short names for the global vendor params
4919 * used by __wlan_hdd_cfg80211_monitor_rssi()
4920 */
4921#undef PARAM_MAX
4922#undef PARAM_CONTROL
4923#undef PARAM_REQUEST_ID
4924#undef PARAM_MAX_RSSI
4925#undef PARAM_MIN_RSSI
4926
4927/**
4928 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4929 * @wiphy: wiphy structure pointer
4930 * @wdev: Wireless device structure pointer
4931 * @data: Pointer to the data received
4932 * @data_len: Length of @data
4933 *
4934 * Return: 0 on success; errno on failure
4935 */
4936static int
4937wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4938 const void *data, int data_len)
4939{
4940 int ret;
4941
4942 cds_ssr_protect(__func__);
4943 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4944 cds_ssr_unprotect(__func__);
4945
4946 return ret;
4947}
4948
4949/**
4950 * hdd_rssi_threshold_breached() - rssi breached NL event
4951 * @hddctx: HDD context
4952 * @data: rssi breached event data
4953 *
4954 * This function reads the rssi breached event %data and fill in the skb with
4955 * NL attributes and send up the NL event.
4956 *
4957 * Return: none
4958 */
4959void hdd_rssi_threshold_breached(void *hddctx,
4960 struct rssi_breach_event *data)
4961{
4962 hdd_context_t *hdd_ctx = hddctx;
4963 struct sk_buff *skb;
4964
4965 ENTER();
4966
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304967 if (wlan_hdd_validate_context(hdd_ctx))
4968 return;
4969 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07004970 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 return;
4972 }
4973
4974 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4975 NULL,
4976 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4977 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4978 GFP_KERNEL);
4979
4980 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07004981 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 return;
4983 }
4984
Jeff Johnson77848112016-06-29 14:52:06 -07004985 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004986 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07004987 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004988 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4989
4990 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4991 data->request_id) ||
4992 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4993 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4994 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4995 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004996 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 goto fail;
4998 }
4999
5000 cfg80211_vendor_event(skb, GFP_KERNEL);
5001 return;
5002
5003fail:
5004 kfree_skb(skb);
5005 return;
5006}
5007
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305008static const struct nla_policy
5009ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5010 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5011};
5012
5013/**
5014 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5015 * @wiphy: Pointer to wireless phy
5016 * @wdev: Pointer to wireless device
5017 * @data: Pointer to data
5018 * @data_len: Length of @data
5019 *
5020 * Return: 0 on success, negative errno on failure
5021 */
5022static int
5023__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5024 struct wireless_dev *wdev,
5025 const void *data, int data_len)
5026{
5027 int status;
5028 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5029 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005030 struct net_device *dev = wdev->netdev;
5031 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305032
5033 ENTER_DEV(wdev->netdev);
5034
5035 status = wlan_hdd_validate_context(pHddCtx);
5036 if (0 != status)
5037 return status;
5038 if (!pHddCtx->config->fhostNSOffload) {
5039 hdd_err("ND Offload not supported");
5040 return -EINVAL;
5041 }
5042
5043 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5044 (struct nlattr *)data,
5045 data_len, ns_offload_set_policy)) {
5046 hdd_err("nla_parse failed");
5047 return -EINVAL;
5048 }
5049
5050 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5051 hdd_err("ND Offload flag attribute not present");
5052 return -EINVAL;
5053 }
5054
5055 pHddCtx->ns_offload_enable =
5056 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5057
Dustin Brownd8279d22016-09-07 14:52:57 -07005058 /* update ns offload in case it is already enabled/disabled */
5059 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5060
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305061 return 0;
5062}
5063
5064/**
5065 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5066 * @wiphy: pointer to wireless wiphy structure.
5067 * @wdev: pointer to wireless_dev structure.
5068 * @data: Pointer to the data to be passed via vendor interface
5069 * @data_len:Length of the data to be passed
5070 *
5071 * Return: Return the Success or Failure code.
5072 */
5073static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5074 struct wireless_dev *wdev,
5075 const void *data, int data_len)
5076{
5077 int ret;
5078
5079 cds_ssr_protect(__func__);
5080 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5081 cds_ssr_unprotect(__func__);
5082
5083 return ret;
5084}
5085
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005086/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5087 * @wiphy: Pointer to wireless phy
5088 * @wdev: Pointer to wireless device
5089 * @data: Pointer to data
5090 * @data_len: Data length
5091 *
5092 * This function return the preferred frequency list generated by the policy
5093 * manager.
5094 *
5095 * Return: success or failure code
5096 */
5097static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5098 struct wireless_dev
5099 *wdev, const void *data,
5100 int data_len)
5101{
5102 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5103 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305104 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305105 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305107 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005108 enum cds_con_mode intf_mode;
5109 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5110 struct sk_buff *reply_skb;
5111
Jeff Johnson1f61b612016-02-12 16:28:33 -08005112 ENTER_DEV(wdev->netdev);
5113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005114 ret = wlan_hdd_validate_context(hdd_ctx);
5115 if (ret)
5116 return -EINVAL;
5117
5118 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5119 data, data_len, NULL)) {
5120 hdd_err("Invalid ATTR");
5121 return -EINVAL;
5122 }
5123
5124 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5125 hdd_err("attr interface type failed");
5126 return -EINVAL;
5127 }
5128
5129 intf_mode = nla_get_u32(tb
5130 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5131
5132 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5133 hdd_err("Invalid interface type");
5134 return -EINVAL;
5135 }
5136
5137 hdd_debug("Userspace requested pref freq list");
5138
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305139 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5140 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305141 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 hdd_err("Get pcl failed");
5143 return -EINVAL;
5144 }
5145
5146 /* convert channel number to frequency */
5147 for (i = 0; i < pcl_len; i++) {
5148 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5149 freq_list[i] =
5150 ieee80211_channel_to_frequency(pcl[i],
5151 IEEE80211_BAND_2GHZ);
5152 else
5153 freq_list[i] =
5154 ieee80211_channel_to_frequency(pcl[i],
5155 IEEE80211_BAND_5GHZ);
5156 }
5157
5158 /* send the freq_list back to supplicant */
5159 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5160 sizeof(u32) *
5161 pcl_len +
5162 NLMSG_HDRLEN);
5163
5164 if (!reply_skb) {
5165 hdd_err("Allocate reply_skb failed");
5166 return -EINVAL;
5167 }
5168
5169 if (nla_put_u32(reply_skb,
5170 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5171 intf_mode) ||
5172 nla_put(reply_skb,
5173 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5174 sizeof(uint32_t) * pcl_len,
5175 freq_list)) {
5176 hdd_err("nla put fail");
5177 kfree_skb(reply_skb);
5178 return -EINVAL;
5179 }
5180
5181 return cfg80211_vendor_cmd_reply(reply_skb);
5182}
5183
5184/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5185 * @wiphy: Pointer to wireless phy
5186 * @wdev: Pointer to wireless device
5187 * @data: Pointer to data
5188 * @data_len: Data length
5189 *
5190 * This function return the preferred frequency list generated by the policy
5191 * manager.
5192 *
5193 * Return: success or failure code
5194 */
5195static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5196 struct wireless_dev
5197 *wdev, const void *data,
5198 int data_len)
5199{
5200 int ret = 0;
5201
5202 cds_ssr_protect(__func__);
5203 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5204 data, data_len);
5205 cds_ssr_unprotect(__func__);
5206
5207 return ret;
5208}
5209
5210/**
5211 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5212 * @wiphy: Pointer to wireless phy
5213 * @wdev: Pointer to wireless device
5214 * @data: Pointer to data
5215 * @data_len: Data length
5216 *
5217 * Return: 0 on success, negative errno on failure
5218 */
5219static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5220 struct wireless_dev *wdev,
5221 const void *data,
5222 int data_len)
5223{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305224 struct net_device *ndev = wdev->netdev;
5225 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005226 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5227 int ret = 0;
5228 enum cds_con_mode intf_mode;
5229 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5230 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231
Jeff Johnson1f61b612016-02-12 16:28:33 -08005232 ENTER_DEV(ndev);
5233
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 ret = wlan_hdd_validate_context(hdd_ctx);
5235 if (ret)
5236 return ret;
5237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5239 data, data_len, NULL)) {
5240 hdd_err("Invalid ATTR");
5241 return -EINVAL;
5242 }
5243
5244 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5245 hdd_err("attr interface type failed");
5246 return -EINVAL;
5247 }
5248
5249 intf_mode = nla_get_u32(tb
5250 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5251
5252 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5253 hdd_err("Invalid interface type");
5254 return -EINVAL;
5255 }
5256
5257 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5258 hdd_err("attr probable freq failed");
5259 return -EINVAL;
5260 }
5261
5262 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5263 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5264
5265 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005266 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005267 channel_hint, HW_MODE_20_MHZ)) {
5268 hdd_err("Set channel hint failed due to concurrency check");
5269 return -EINVAL;
5270 }
5271
Krunal Soni09e55032016-06-07 10:06:55 -07005272 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5273 hdd_warn("Remain On Channel Pending");
5274
Krunal Soni3091bcc2016-06-23 12:28:21 -07005275 ret = qdf_reset_connection_update();
5276 if (!QDF_IS_STATUS_SUCCESS(ret))
5277 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005278
Krunal Soni3091bcc2016-06-23 12:28:21 -07005279 ret = cds_current_connections_update(adapter->sessionId,
5280 channel_hint,
5281 SIR_UPDATE_REASON_SET_OPER_CHAN);
5282 if (QDF_STATUS_E_FAILURE == ret) {
5283 /* return in the failure case */
5284 hdd_err("ERROR: connections update failed!!");
5285 return -EINVAL;
5286 }
5287
5288 if (QDF_STATUS_SUCCESS == ret) {
5289 /*
5290 * Success is the only case for which we expect hw mode
5291 * change to take place, hence we need to wait.
5292 * For any other return value it should be a pass
5293 * through
5294 */
5295 ret = qdf_wait_for_connection_update();
5296 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5297 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005298 return -EINVAL;
5299 }
5300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301 }
5302
5303 return 0;
5304}
5305
5306/**
5307 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5308 * @wiphy: Pointer to wireless phy
5309 * @wdev: Pointer to wireless device
5310 * @data: Pointer to data
5311 * @data_len: Data length
5312 *
5313 * Return: 0 on success, negative errno on failure
5314 */
5315static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5316 struct wireless_dev *wdev,
5317 const void *data,
5318 int data_len)
5319{
5320 int ret = 0;
5321
5322 cds_ssr_protect(__func__);
5323 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5324 data, data_len);
5325 cds_ssr_unprotect(__func__);
5326
5327 return ret;
5328}
5329
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305330static const struct
5331nla_policy
5332qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5333 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5334};
5335
5336/**
5337 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5338 * @wiphy: WIPHY structure pointer
5339 * @wdev: Wireless device structure pointer
5340 * @data: Pointer to the data received
5341 * @data_len: Length of the data received
5342 *
5343 * This function is used to get link properties like nss, rate flags and
5344 * operating frequency for the active connection with the given peer.
5345 *
5346 * Return: 0 on success and errno on failure
5347 */
5348static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5349 struct wireless_dev *wdev,
5350 const void *data,
5351 int data_len)
5352{
5353 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5354 struct net_device *dev = wdev->netdev;
5355 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5356 hdd_station_ctx_t *hdd_sta_ctx;
5357 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305358 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305359 uint32_t sta_id;
5360 struct sk_buff *reply_skb;
5361 uint32_t rate_flags = 0;
5362 uint8_t nss;
5363 uint8_t final_rate_flags = 0;
5364 uint32_t freq;
5365
Jeff Johnson1f61b612016-02-12 16:28:33 -08005366 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305367
Anurag Chouhan6d760662016-02-20 16:05:43 +05305368 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305369 hdd_err("Command not allowed in FTM mode");
5370 return -EPERM;
5371 }
5372
5373 if (0 != wlan_hdd_validate_context(hdd_ctx))
5374 return -EINVAL;
5375
5376 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5377 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005378 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305379 return -EINVAL;
5380 }
5381
5382 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005383 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305384 adapter->device_mode);
5385 return -EINVAL;
5386 }
5387
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305388 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305389 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005390 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305391 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5392
Krunal Sonib4326f22016-03-10 13:05:51 -08005393 if (adapter->device_mode == QDF_STA_MODE ||
5394 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305395 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5396 if ((hdd_sta_ctx->conn_info.connState !=
5397 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305398 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305399 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005400 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305401 MAC_ADDR_ARRAY(peer_mac));
5402 return -EINVAL;
5403 }
5404
5405 nss = hdd_sta_ctx->conn_info.nss;
5406 freq = cds_chan_to_freq(
5407 hdd_sta_ctx->conn_info.operationChannel);
5408 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005409 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5410 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305411
5412 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5413 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305414 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305415 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305416 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305417 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305418 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305419 break;
5420 }
5421
5422 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005423 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305424 MAC_ADDR_ARRAY(peer_mac));
5425 return -EINVAL;
5426 }
5427
5428 nss = adapter->aStaInfo[sta_id].nss;
5429 freq = cds_chan_to_freq(
5430 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5431 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5432 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005433 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305434 MAC_ADDR_ARRAY(peer_mac));
5435 return -EINVAL;
5436 }
5437
5438 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5439 if (rate_flags & eHAL_TX_RATE_VHT80) {
5440 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005441#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305442 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005443#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305444 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5445 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005446#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305447 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005448#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305449 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5450 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5451 } else if (rate_flags &
5452 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5453 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005454#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305455 if (rate_flags & eHAL_TX_RATE_HT40)
5456 final_rate_flags |=
5457 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005458#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305459 }
5460
5461 if (rate_flags & eHAL_TX_RATE_SGI) {
5462 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5463 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5464 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5465 }
5466 }
5467
5468 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5469 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5470
5471 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005472 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305473 return -EINVAL;
5474 }
5475
5476 if (nla_put_u8(reply_skb,
5477 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5478 nss) ||
5479 nla_put_u8(reply_skb,
5480 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5481 final_rate_flags) ||
5482 nla_put_u32(reply_skb,
5483 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5484 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005485 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305486 kfree_skb(reply_skb);
5487 return -EINVAL;
5488 }
5489
5490 return cfg80211_vendor_cmd_reply(reply_skb);
5491}
5492
5493/**
5494 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5495 * properties.
5496 * @wiphy: WIPHY structure pointer
5497 * @wdev: Wireless device structure pointer
5498 * @data: Pointer to the data received
5499 * @data_len: Length of the data received
5500 *
5501 * This function is used to get link properties like nss, rate flags and
5502 * operating frequency for the active connection with the given peer.
5503 *
5504 * Return: 0 on success and errno on failure
5505 */
5506static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5507 struct wireless_dev *wdev,
5508 const void *data,
5509 int data_len)
5510{
5511 int ret = 0;
5512
5513 cds_ssr_protect(__func__);
5514 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5515 wdev, data, data_len);
5516 cds_ssr_unprotect(__func__);
5517
5518 return ret;
5519}
5520
Peng Xu278d0122015-09-24 16:34:17 -07005521static const struct
5522nla_policy
5523qca_wlan_vendor_ota_test_policy
5524[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5525 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5526};
5527
5528/**
5529 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5530 * @wiphy: Pointer to wireless phy
5531 * @wdev: Pointer to wireless device
5532 * @data: Pointer to data
5533 * @data_len: Data length
5534 *
5535 * Return: 0 on success, negative errno on failure
5536 */
5537static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5538 struct wireless_dev *wdev,
5539 const void *data,
5540 int data_len)
5541{
5542 struct net_device *dev = wdev->netdev;
5543 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5544 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5545 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5546 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5547 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305548 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005549 uint32_t current_roam_state;
5550
Jeff Johnson1f61b612016-02-12 16:28:33 -08005551 ENTER_DEV(dev);
5552
Anurag Chouhan6d760662016-02-20 16:05:43 +05305553 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005554 hdd_err("Command not allowed in FTM mode");
5555 return -EPERM;
5556 }
5557
5558 if (0 != wlan_hdd_validate_context(hdd_ctx))
5559 return -EINVAL;
5560
5561 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5562 data, data_len,
5563 qca_wlan_vendor_ota_test_policy)) {
5564 hdd_err("invalid attr");
5565 return -EINVAL;
5566 }
5567
5568 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5569 hdd_err("attr ota test failed");
5570 return -EINVAL;
5571 }
5572
5573 ota_enable = nla_get_u8(
5574 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5575
5576 hdd_info(" OTA test enable = %d", ota_enable);
5577 if (ota_enable != 1) {
5578 hdd_err("Invalid value, only enable test mode is supported!");
5579 return -EINVAL;
5580 }
5581
5582 current_roam_state =
5583 sme_get_current_roam_state(hal, adapter->sessionId);
5584 status = sme_stop_roaming(hal, adapter->sessionId,
5585 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305586 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005587 hdd_err("Enable/Disable roaming failed");
5588 return -EINVAL;
5589 }
5590
5591 status = sme_ps_enable_disable(hal, adapter->sessionId,
5592 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305593 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005594 hdd_err("Enable/Disable power save failed");
5595 /* restore previous roaming setting */
5596 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5597 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5598 status = sme_start_roaming(hal, adapter->sessionId,
5599 eCsrHddIssued);
5600 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5601 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5602 status = sme_stop_roaming(hal, adapter->sessionId,
5603 eCsrHddIssued);
5604
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305605 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005606 hdd_err("Restoring roaming state failed");
5607
5608 return -EINVAL;
5609 }
5610
5611
5612 return 0;
5613}
5614
5615/**
5616 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5617 * @wiphy: Pointer to wireless phy
5618 * @wdev: Pointer to wireless device
5619 * @data: Pointer to data
5620 * @data_len: Data length
5621 *
5622 * Return: 0 on success, negative errno on failure
5623 */
5624static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5625 struct wireless_dev *wdev,
5626 const void *data,
5627 int data_len)
5628{
5629 int ret = 0;
5630
5631 cds_ssr_protect(__func__);
5632 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5633 cds_ssr_unprotect(__func__);
5634
5635 return ret;
5636}
5637
Peng Xu4d67c8f2015-10-16 16:02:26 -07005638/**
5639 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5640 * @wiphy: Pointer to wireless phy
5641 * @wdev: Pointer to wireless device
5642 * @data: Pointer to data
5643 * @data_len: Data length
5644 *
5645 * Return: 0 on success, negative errno on failure
5646 */
5647static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5648 struct wireless_dev *wdev,
5649 const void *data,
5650 int data_len)
5651{
5652 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5653 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005654 hdd_adapter_t *adapter;
5655 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005656 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5657 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005658 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005659
Jeff Johnson1f61b612016-02-12 16:28:33 -08005660 ENTER_DEV(dev);
5661
Peng Xu4d67c8f2015-10-16 16:02:26 -07005662 ret = wlan_hdd_validate_context(hdd_ctx);
5663 if (ret)
5664 return ret;
5665
5666 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5667
5668 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5669 data, data_len, NULL)) {
5670 hdd_err("Invalid ATTR");
5671 return -EINVAL;
5672 }
5673
5674 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5675 hdd_err("attr tx power scale failed");
5676 return -EINVAL;
5677 }
5678
5679 scale_value = nla_get_u8(tb
5680 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5681
5682 if (scale_value > MAX_TXPOWER_SCALE) {
5683 hdd_err("Invalid tx power scale level");
5684 return -EINVAL;
5685 }
5686
Peng Xu62c8c432016-05-09 15:23:02 -07005687 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005688
Peng Xu62c8c432016-05-09 15:23:02 -07005689 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005690 hdd_err("Set tx power scale failed");
5691 return -EINVAL;
5692 }
5693
5694 return 0;
5695}
5696
5697/**
5698 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5699 * @wiphy: Pointer to wireless phy
5700 * @wdev: Pointer to wireless device
5701 * @data: Pointer to data
5702 * @data_len: Data length
5703 *
5704 * Return: 0 on success, negative errno on failure
5705 */
5706static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5707 struct wireless_dev *wdev,
5708 const void *data,
5709 int data_len)
5710{
Peng Xu62c8c432016-05-09 15:23:02 -07005711 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005712
5713 cds_ssr_protect(__func__);
5714 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5715 data, data_len);
5716 cds_ssr_unprotect(__func__);
5717
5718 return ret;
5719}
5720
5721/**
5722 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5723 * @wiphy: Pointer to wireless phy
5724 * @wdev: Pointer to wireless device
5725 * @data: Pointer to data
5726 * @data_len: Data length
5727 *
5728 * Return: 0 on success, negative errno on failure
5729 */
5730static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5731 struct wireless_dev *wdev,
5732 const void *data,
5733 int data_len)
5734{
5735 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5736 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005737 hdd_adapter_t *adapter;
5738 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005739 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5740 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005741 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005742
Jeff Johnson1f61b612016-02-12 16:28:33 -08005743 ENTER_DEV(dev);
5744
Peng Xu4d67c8f2015-10-16 16:02:26 -07005745 ret = wlan_hdd_validate_context(hdd_ctx);
5746 if (ret)
5747 return ret;
5748
5749 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5750
5751 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5752 data, data_len, NULL)) {
5753 hdd_err("Invalid ATTR");
5754 return -EINVAL;
5755 }
5756
5757 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5758 hdd_err("attr tx power decrease db value failed");
5759 return -EINVAL;
5760 }
5761
5762 scale_value = nla_get_u8(tb
5763 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5764
Peng Xu62c8c432016-05-09 15:23:02 -07005765 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5766 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005767
Peng Xu62c8c432016-05-09 15:23:02 -07005768 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005769 hdd_err("Set tx power decrease db failed");
5770 return -EINVAL;
5771 }
5772
5773 return 0;
5774}
5775
5776/**
5777 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5778 * @wiphy: Pointer to wireless phy
5779 * @wdev: Pointer to wireless device
5780 * @data: Pointer to data
5781 * @data_len: Data length
5782 *
5783 * Return: 0 on success, negative errno on failure
5784 */
5785static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5786 struct wireless_dev *wdev,
5787 const void *data,
5788 int data_len)
5789{
Peng Xu62c8c432016-05-09 15:23:02 -07005790 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005791
5792 cds_ssr_protect(__func__);
5793 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5794 data, data_len);
5795 cds_ssr_unprotect(__func__);
5796
5797 return ret;
5798}
Peng Xu8fdaa492016-06-22 10:20:47 -07005799
5800/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305801 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5802 * @wiphy: Pointer to wireless phy
5803 * @wdev: Pointer to wireless device
5804 * @data: Pointer to data
5805 * @data_len: Data length
5806 *
5807 * Processes the conditional channel switch request and invokes the helper
5808 * APIs to process the channel switch request.
5809 *
5810 * Return: 0 on success, negative errno on failure
5811 */
5812static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5813 struct wireless_dev *wdev,
5814 const void *data,
5815 int data_len)
5816{
5817 int ret;
5818 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5819 struct net_device *dev = wdev->netdev;
5820 hdd_adapter_t *adapter;
5821 struct nlattr
5822 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5823 uint32_t freq_len, i;
5824 uint32_t *freq;
5825 uint8_t chans[QDF_MAX_NUM_CHAN];
5826
5827 ENTER_DEV(dev);
5828
5829 ret = wlan_hdd_validate_context(hdd_ctx);
5830 if (ret)
5831 return ret;
5832
5833 if (!hdd_ctx->config->enableDFSMasterCap) {
5834 hdd_err("DFS master capability is not present in the driver");
5835 return -EINVAL;
5836 }
5837
5838 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5839 hdd_err("Command not allowed in FTM mode");
5840 return -EPERM;
5841 }
5842
5843 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5844 if (adapter->device_mode != QDF_SAP_MODE) {
5845 hdd_err("Invalid device mode %d", adapter->device_mode);
5846 return -EINVAL;
5847 }
5848
5849 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5850 data, data_len, NULL)) {
5851 hdd_err("Invalid ATTR");
5852 return -EINVAL;
5853 }
5854
5855 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5856 hdd_err("Frequency list is missing");
5857 return -EINVAL;
5858 }
5859
5860 freq_len = nla_len(
5861 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5862 sizeof(uint32_t);
5863
5864 if (freq_len > QDF_MAX_NUM_CHAN) {
5865 hdd_err("insufficient space to hold channels");
5866 return -ENOMEM;
5867 }
5868
5869 hdd_debug("freq_len=%d", freq_len);
5870
5871 freq = nla_data(
5872 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5873
5874
5875 for (i = 0; i < freq_len; i++) {
5876 if (freq[i] == 0)
5877 chans[i] = 0;
5878 else
5879 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5880
5881 hdd_debug("freq[%d]=%d", i, freq[i]);
5882 }
5883
5884 /*
5885 * The input frequency list from user space is designed to be a
5886 * priority based frequency list. This is only to accommodate any
5887 * future request. But, current requirement is only to perform CAC
5888 * on a single channel. So, the first entry from the list is picked.
5889 *
5890 * If channel is zero, any channel in the available outdoor regulatory
5891 * domain will be selected.
5892 */
5893 ret = wlan_hdd_request_pre_cac(chans[0]);
5894 if (ret) {
5895 hdd_err("pre cac request failed with reason:%d", ret);
5896 return ret;
5897 }
5898
5899 return 0;
5900}
5901
5902/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005903 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5904 * @wiphy: Pointer to wireless phy
5905 * @wdev: Pointer to wireless device
5906 * @data: Pointer to data
5907 * @data_len: Data length
5908 *
5909 * This function is to process the p2p listen offload start vendor
5910 * command. It parses the input parameters and invoke WMA API to
5911 * send the command to firmware.
5912 *
5913 * Return: 0 on success, negative errno on failure
5914 */
5915static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5916 struct wireless_dev *wdev,
5917 const void *data,
5918 int data_len)
5919{
5920 int ret;
5921 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5922 struct net_device *dev = wdev->netdev;
5923 hdd_adapter_t *adapter;
5924 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5925 struct sir_p2p_lo_start params;
5926 QDF_STATUS status;
5927
5928 ENTER_DEV(dev);
5929
5930 ret = wlan_hdd_validate_context(hdd_ctx);
5931 if (ret)
5932 return ret;
5933
5934 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5935 hdd_err("Command not allowed in FTM mode");
5936 return -EPERM;
5937 }
5938
5939 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5940 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5941 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5942 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5943 hdd_err("Invalid device mode %d", adapter->device_mode);
5944 return -EINVAL;
5945 }
5946
5947 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5948 data, data_len, NULL)) {
5949 hdd_err("Invalid ATTR");
5950 return -EINVAL;
5951 }
5952
5953 memset(&params, 0, sizeof(params));
5954
5955 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5956 params.ctl_flags = 1; /* set to default value */
5957 else
5958 params.ctl_flags = nla_get_u32(tb
5959 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5960
5961 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5962 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5963 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
5964 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
5965 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
5966 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
5967 hdd_err("Attribute parsing failed");
5968 return -EINVAL;
5969 }
5970
5971 params.vdev_id = adapter->sessionId;
5972 params.freq = nla_get_u32(tb
5973 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
5974 if ((params.freq != 2412) && (params.freq != 2437) &&
5975 (params.freq != 2462)) {
5976 hdd_err("Invalid listening channel: %d", params.freq);
5977 return -EINVAL;
5978 }
5979
5980 params.period = nla_get_u32(tb
5981 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
5982 if (!((params.period > 0) && (params.period < UINT_MAX))) {
5983 hdd_err("Invalid period: %d", params.period);
5984 return -EINVAL;
5985 }
5986
5987 params.interval = nla_get_u32(tb
5988 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
5989 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
5990 hdd_err("Invalid interval: %d", params.interval);
5991 return -EINVAL;
5992 }
5993
5994 params.count = nla_get_u32(tb
5995 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
5996 if (!((params.count > 0) && (params.count < UINT_MAX))) {
5997 hdd_err("Invalid count: %d", params.count);
5998 return -EINVAL;
5999 }
6000
6001 params.device_types = nla_data(tb
6002 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6003 if (params.device_types == NULL) {
6004 hdd_err("Invalid device types");
6005 return -EINVAL;
6006 }
6007
6008 params.dev_types_len = nla_len(tb
6009 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6010 if (params.dev_types_len < 8) {
6011 hdd_err("Invalid device type length: %d", params.dev_types_len);
6012 return -EINVAL;
6013 }
6014
6015 params.probe_resp_tmplt = nla_data(tb
6016 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6017 if (params.probe_resp_tmplt == NULL) {
6018 hdd_err("Invalid probe response template");
6019 return -EINVAL;
6020 }
6021
6022 params.probe_resp_len = nla_len(tb
6023 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6024 if (params.probe_resp_len == 0) {
6025 hdd_err("Invalid probe resp template length: %d",
6026 params.probe_resp_len);
6027 return -EINVAL;
6028 }
6029
6030 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6031 params.freq, params.period, params.interval, params.count);
6032
6033 status = wma_p2p_lo_start(&params);
6034
6035 if (!QDF_IS_STATUS_SUCCESS(status)) {
6036 hdd_err("P2P LO start failed");
6037 return -EINVAL;
6038 }
6039
6040 return 0;
6041}
6042
6043
6044/**
6045 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6046 * @wiphy: Pointer to wireless phy
6047 * @wdev: Pointer to wireless device
6048 * @data: Pointer to data
6049 * @data_len: Data length
6050 *
6051 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6052 * to process p2p listen offload start vendor command.
6053 *
6054 * Return: 0 on success, negative errno on failure
6055 */
6056static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6057 struct wireless_dev *wdev,
6058 const void *data,
6059 int data_len)
6060{
6061 int ret = 0;
6062
6063 cds_ssr_protect(__func__);
6064 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6065 data, data_len);
6066 cds_ssr_unprotect(__func__);
6067
6068 return ret;
6069}
6070
6071/**
6072 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6073 * @wiphy: Pointer to wireless phy
6074 * @wdev: Pointer to wireless device
6075 * @data: Pointer to data
6076 * @data_len: Data length
6077 *
6078 * This function is to process the p2p listen offload stop vendor
6079 * command. It invokes WMA API to send command to firmware.
6080 *
6081 * Return: 0 on success, negative errno on failure
6082 */
6083static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6084 struct wireless_dev *wdev,
6085 const void *data,
6086 int data_len)
6087{
6088 QDF_STATUS status;
6089 hdd_adapter_t *adapter;
6090 struct net_device *dev = wdev->netdev;
6091
6092 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6093 hdd_err("Command not allowed in FTM mode");
6094 return -EPERM;
6095 }
6096
6097 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6098 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6099 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6100 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6101 hdd_err("Invalid device mode");
6102 return -EINVAL;
6103 }
6104
6105 status = wma_p2p_lo_stop(adapter->sessionId);
6106
6107 if (!QDF_IS_STATUS_SUCCESS(status)) {
6108 hdd_err("P2P LO stop failed");
6109 return -EINVAL;
6110 }
6111
6112 return 0;
6113}
6114
6115/**
6116 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6117 * @wiphy: Pointer to wireless phy
6118 * @wdev: Pointer to wireless device
6119 * @data: Pointer to data
6120 * @data_len: Data length
6121 *
6122 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6123 * to process p2p listen offload stop vendor command.
6124 *
6125 * Return: 0 on success, negative errno on failure
6126 */
6127static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6128 struct wireless_dev *wdev,
6129 const void *data,
6130 int data_len)
6131{
6132 int ret = 0;
6133
6134 cds_ssr_protect(__func__);
6135 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6136 data, data_len);
6137 cds_ssr_unprotect(__func__);
6138
6139 return ret;
6140}
6141
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306142/**
6143 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6144 * @wiphy: Pointer to wireless phy
6145 * @wdev: Pointer to wireless device
6146 * @data: Pointer to data
6147 * @data_len: Data length
6148 *
6149 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6150 * to process the conditional channel switch request.
6151 *
6152 * Return: 0 on success, negative errno on failure
6153 */
6154static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6155 struct wireless_dev *wdev,
6156 const void *data,
6157 int data_len)
6158{
6159 int ret;
6160
6161 cds_ssr_protect(__func__);
6162 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6163 data, data_len);
6164 cds_ssr_unprotect(__func__);
6165
6166 return ret;
6167}
6168
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306169/*
6170 * define short names for the global vendor params
6171 * used by __wlan_hdd_cfg80211_bpf_offload()
6172 */
6173#define BPF_INVALID \
6174 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6175#define BPF_SET_RESET \
6176 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6177#define BPF_VERSION \
6178 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6179#define BPF_FILTER_ID \
6180 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6181#define BPF_PACKET_SIZE \
6182 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6183#define BPF_CURRENT_OFFSET \
6184 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6185#define BPF_PROGRAM \
6186 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6187#define BPF_MAX \
6188 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006189
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306190static const struct nla_policy
6191wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6192 [BPF_SET_RESET] = {.type = NLA_U32},
6193 [BPF_VERSION] = {.type = NLA_U32},
6194 [BPF_FILTER_ID] = {.type = NLA_U32},
6195 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6196 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6197 [BPF_PROGRAM] = {.type = NLA_U8},
6198};
6199
6200/**
6201 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6202 * @hdd_context: hdd_context
6203 * @bpf_get_offload: struct for get offload
6204 *
6205 * This function receives the response/data from the lower layer and
6206 * checks to see if the thread is still waiting then post the results to
6207 * upper layer, if the request has timed out then ignore.
6208 *
6209 * Return: None
6210 */
6211void hdd_get_bpf_offload_cb(void *hdd_context,
6212 struct sir_bpf_get_offload *data)
6213{
6214 hdd_context_t *hdd_ctx = hdd_context;
6215 struct hdd_bpf_context *context;
6216
6217 ENTER();
6218
6219 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006220 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306221 data);
6222 return;
6223 }
6224
6225 spin_lock(&hdd_context_lock);
6226
6227 context = &bpf_context;
6228 /* The caller presumably timed out so there is nothing we can do */
6229 if (context->magic != BPF_CONTEXT_MAGIC) {
6230 spin_unlock(&hdd_context_lock);
6231 return;
6232 }
6233
6234 /* context is valid so caller is still waiting */
6235 /* paranoia: invalidate the magic */
6236 context->magic = 0;
6237
6238 context->capability_response = *data;
6239 complete(&context->completion);
6240
6241 spin_unlock(&hdd_context_lock);
6242
6243 return;
6244}
6245
6246/**
6247 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6248 * @hdd_context: hdd_context
6249 * @bpf_get_offload: struct for get offload
6250 *
6251 * Return: 0 on success, error number otherwise.
6252 */
6253static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6254 struct sir_bpf_get_offload *bpf_get_offload)
6255{
6256 struct sk_buff *skb;
6257 uint32_t nl_buf_len;
6258
6259 ENTER();
6260
6261 nl_buf_len = NLMSG_HDRLEN;
6262 nl_buf_len +=
6263 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6264 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6265
6266 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6267 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006268 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306269 return -ENOMEM;
6270 }
6271
Jeff Johnson77848112016-06-29 14:52:06 -07006272 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306273 bpf_get_offload->bpf_version,
6274 bpf_get_offload->max_bytes_for_bpf_inst);
6275
6276 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6277 bpf_get_offload->max_bytes_for_bpf_inst) ||
6278 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006279 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306280 goto nla_put_failure;
6281 }
6282
6283 cfg80211_vendor_cmd_reply(skb);
6284 EXIT();
6285 return 0;
6286
6287nla_put_failure:
6288 kfree_skb(skb);
6289 return -EINVAL;
6290}
6291
6292/**
6293 * hdd_get_bpf_offload - Get BPF offload Capabilities
6294 * @hdd_ctx: Hdd context
6295 *
6296 * Return: 0 on success, errno on failure
6297 */
6298static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6299{
6300 unsigned long rc;
6301 struct hdd_bpf_context *context;
6302 QDF_STATUS status;
6303 int ret;
6304
6305 ENTER();
6306
6307 spin_lock(&hdd_context_lock);
6308 context = &bpf_context;
6309 context->magic = BPF_CONTEXT_MAGIC;
6310 INIT_COMPLETION(context->completion);
6311 spin_unlock(&hdd_context_lock);
6312
6313 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6314 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006315 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306316 return -EINVAL;
6317 }
6318 /* request was sent -- wait for the response */
6319 rc = wait_for_completion_timeout(&context->completion,
6320 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6321 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006322 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306323 spin_lock(&hdd_context_lock);
6324 context->magic = 0;
6325 spin_unlock(&hdd_context_lock);
6326
6327 return -ETIMEDOUT;
6328 }
6329 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6330 &bpf_context.capability_response);
6331 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006332 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306333
6334 EXIT();
6335 return ret;
6336}
6337
6338/**
6339 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6340 * @hdd_ctx: Hdd context
6341 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306342 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306343 *
6344 * Return: 0 on success; errno on failure
6345 */
6346static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6347 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306348 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306349{
6350 struct sir_bpf_set_offload *bpf_set_offload;
6351 QDF_STATUS status;
6352 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306353 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306354
6355 ENTER();
6356
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306357 if (adapter->device_mode == QDF_STA_MODE ||
6358 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6359 if (!hdd_conn_is_connected(
6360 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6361 hdd_err("Not in Connected state!");
6362 return -ENOTSUPP;
6363 }
6364 }
6365
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306366 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6367 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006368 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306369 return -ENOMEM;
6370 }
6371 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6372
6373 /* Parse and fetch bpf packet size */
6374 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006375 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306376 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306377 goto fail;
6378 }
6379 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6380
6381 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006382 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306383 goto post_sme;
6384 }
6385
6386 /* Parse and fetch bpf program */
6387 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006388 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306389 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306390 goto fail;
6391 }
6392
6393 prog_len = nla_len(tb[BPF_PROGRAM]);
6394 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306395
6396 if (bpf_set_offload->program == NULL) {
6397 hdd_err("qdf_mem_malloc failed for bpf offload program");
6398 ret = -ENOMEM;
6399 goto fail;
6400 }
6401
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306402 bpf_set_offload->current_length = prog_len;
6403 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306404 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306405
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306406 hdd_info("BPF set instructions");
6407 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6408 bpf_set_offload->program, prog_len);
6409
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306410 /* Parse and fetch filter Id */
6411 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006412 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306413 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306414 goto fail;
6415 }
6416 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6417
6418 /* Parse and fetch current offset */
6419 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006420 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306421 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306422 goto fail;
6423 }
6424 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6425
6426post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006427 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 +05306428 bpf_set_offload->session_id,
6429 bpf_set_offload->version,
6430 bpf_set_offload->filter_id,
6431 bpf_set_offload->total_length,
6432 bpf_set_offload->current_length,
6433 bpf_set_offload->current_offset);
6434
6435 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6436 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006437 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306438 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306439 goto fail;
6440 }
6441 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306442
6443fail:
6444 if (bpf_set_offload->current_length)
6445 qdf_mem_free(bpf_set_offload->program);
6446 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306447 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306448}
6449
6450/**
6451 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6452 * @wiphy: wiphy structure pointer
6453 * @wdev: Wireless device structure pointer
6454 * @data: Pointer to the data received
6455 * @data_len: Length of @data
6456 *
6457 * Return: 0 on success; errno on failure
6458 */
6459static int
6460__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6461 struct wireless_dev *wdev,
6462 const void *data, int data_len)
6463{
6464 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6465 struct net_device *dev = wdev->netdev;
6466 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6467 struct nlattr *tb[BPF_MAX + 1];
6468 int ret_val, packet_filter_subcmd;
6469
6470 ENTER();
6471
6472 ret_val = wlan_hdd_validate_context(hdd_ctx);
6473 if (ret_val)
6474 return ret_val;
6475
6476 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006477 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306478 return -EINVAL;
6479 }
6480
6481 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006482 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306483 return -ENOTSUPP;
6484 }
6485
6486 if (nla_parse(tb, BPF_MAX, data, data_len,
6487 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006488 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306489 return -EINVAL;
6490 }
6491
6492 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006493 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306494 return -EINVAL;
6495 }
6496
6497 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6498
6499 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6500 return hdd_get_bpf_offload(hdd_ctx);
6501 else
6502 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306503 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306504}
6505
6506/**
6507 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6508 * @wiphy: wiphy structure pointer
6509 * @wdev: Wireless device structure pointer
6510 * @data: Pointer to the data received
6511 * @data_len: Length of @data
6512 *
6513 * Return: 0 on success; errno on failure
6514 */
6515
6516static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6517 struct wireless_dev *wdev,
6518 const void *data, int data_len)
6519{
6520 int ret;
6521
6522 cds_ssr_protect(__func__);
6523 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6524 cds_ssr_unprotect(__func__);
6525
6526 return ret;
6527}
6528
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306529/**
6530 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6531 * @pre_cac_adapter: AP adapter used for pre cac
6532 * @status: Status (true or false)
6533 * @handle: Global handle
6534 *
6535 * Sets the status of pre cac i.e., whether the pre cac is active or not
6536 *
6537 * Return: Zero on success, non-zero on failure
6538 */
6539static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6540 bool status, tHalHandle handle)
6541{
6542 QDF_STATUS ret;
6543
6544 ret = wlan_sap_set_pre_cac_status(
6545 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6546 if (QDF_IS_STATUS_ERROR(ret))
6547 return -EINVAL;
6548
6549 return 0;
6550}
6551
6552/**
6553 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6554 * @ap_adapter: AP adapter
6555 * @chan_before_pre_cac: Channel
6556 *
6557 * Saves the channel which the AP was beaconing on before moving to the pre
6558 * cac channel. If radar is detected on the pre cac channel, this saved
6559 * channel will be used for AP operations.
6560 *
6561 * Return: Zero on success, non-zero on failure
6562 */
6563static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6564 uint8_t chan_before_pre_cac)
6565{
6566 QDF_STATUS ret;
6567
6568 ret = wlan_sap_set_chan_before_pre_cac(
6569 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6570 if (QDF_IS_STATUS_ERROR(ret))
6571 return -EINVAL;
6572
6573 return 0;
6574}
6575
6576/**
6577 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6578 * @ap_adapter: AP adapter
6579 * @nol: Non-occupancy list
6580 * @nol_len: Length of NOL
6581 *
6582 * Get the NOL for SAP
6583 *
6584 * Return: Zero on success, non-zero on failure
6585 */
6586static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6587 uint32_t *nol_len)
6588{
6589 QDF_STATUS ret;
6590
6591 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6592 nol, nol_len);
6593 if (QDF_IS_STATUS_ERROR(ret))
6594 return -EINVAL;
6595
6596 return 0;
6597}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306598
6599/**
6600 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6601 * @hdd_ctx: HDD context
6602 * @ap_adapter: AP adapter
6603 * @channel: Channel requested by userspace
6604 * @pre_cac_chan: Pointer to the pre CAC channel
6605 *
6606 * Validates the channel provided by userspace. If user provided channel 0,
6607 * a valid outdoor channel must be selected from the regulatory channel.
6608 *
6609 * Return: Zero on success and non zero value on error
6610 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006611static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6612 hdd_adapter_t *ap_adapter,
6613 uint8_t channel,
6614 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306615{
6616 uint32_t i, j;
6617 QDF_STATUS status;
6618 int ret;
6619 uint8_t nol[QDF_MAX_NUM_CHAN];
6620 uint32_t nol_len = 0, weight_len = 0;
6621 bool found;
6622 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6623 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6624 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6625
6626 if (0 == channel) {
6627 /* Channel is not obtained from PCL because PCL may not have
6628 * the entire channel list. For example: if SAP is up on
6629 * channel 6 and PCL is queried for the next SAP interface,
6630 * if SCC is preferred, the PCL will contain only the channel
6631 * 6. But, we are in need of a DFS channel. So, going with the
6632 * first channel from the valid channel list.
6633 */
6634 status = cds_get_valid_chans(channel_list, &len);
6635 if (QDF_IS_STATUS_ERROR(status)) {
6636 hdd_err("Failed to get channel list");
6637 return -EINVAL;
6638 }
6639 cds_update_with_safe_channel_list(channel_list, &len,
6640 pcl_weights, weight_len);
6641 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6642 for (i = 0; i < len; i++) {
6643 found = false;
6644 for (j = 0; j < nol_len; j++) {
6645 if (channel_list[i] == nol[j]) {
6646 found = true;
6647 break;
6648 }
6649 }
6650 if (found)
6651 continue;
6652 if (CDS_IS_DFS_CH(channel_list[i])) {
6653 *pre_cac_chan = channel_list[i];
6654 break;
6655 }
6656 }
6657 if (*pre_cac_chan == 0) {
6658 hdd_err("unable to find outdoor channel");
6659 return -EINVAL;
6660 }
6661 } else {
6662 /* Only when driver selects a channel, check is done for
6663 * unnsafe and NOL channels. When user provides a fixed channel
6664 * the user is expected to take care of this.
6665 */
6666 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6667 !CDS_IS_DFS_CH(channel)) {
6668 hdd_err("Invalid channel for pre cac:%d", channel);
6669 return -EINVAL;
6670 } else {
6671 *pre_cac_chan = channel;
6672 }
6673 }
6674 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6675 return 0;
6676}
6677
6678/**
6679 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6680 * @channel: Channel option provided by userspace
6681 *
6682 * Sets the driver to the required hardware mode and start an adapater for
6683 * pre CAC which will mimic an AP.
6684 *
6685 * Return: Zero on success, non-zero value on error
6686 */
6687int wlan_hdd_request_pre_cac(uint8_t channel)
6688{
6689 uint8_t pre_cac_chan = 0;
6690 hdd_context_t *hdd_ctx;
6691 int ret;
6692 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6693 hdd_ap_ctx_t *hdd_ap_ctx;
6694 QDF_STATUS status;
6695 struct wiphy *wiphy;
6696 struct net_device *dev;
6697 struct cfg80211_chan_def chandef;
6698 enum nl80211_channel_type channel_type;
6699 uint32_t freq;
6700 struct ieee80211_channel *chan;
6701 tHalHandle handle;
6702 bool val;
6703
6704 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6705 if (0 != wlan_hdd_validate_context(hdd_ctx))
6706 return -EINVAL;
6707
6708 if (cds_get_connection_count() > 1) {
6709 hdd_err("pre cac not allowed in concurrency");
6710 return -EINVAL;
6711 }
6712
6713 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6714 if (!ap_adapter) {
6715 hdd_err("unable to get SAP adapter");
6716 return -EINVAL;
6717 }
6718
6719 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6720 if (!handle) {
6721 hdd_err("Invalid handle");
6722 return -EINVAL;
6723 }
6724
6725 val = wlan_sap_is_pre_cac_active(handle);
6726 if (val) {
6727 hdd_err("pre cac is already in progress");
6728 return -EINVAL;
6729 }
6730
6731 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6732 if (!hdd_ap_ctx) {
6733 hdd_err("SAP context is NULL");
6734 return -EINVAL;
6735 }
6736
6737 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6738 hdd_err("SAP is already on DFS channel:%d",
6739 hdd_ap_ctx->operatingChannel);
6740 return -EINVAL;
6741 }
6742
6743 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6744 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6745 hdd_ap_ctx->operatingChannel);
6746 return -EINVAL;
6747 }
6748
6749 hdd_info("channel:%d", channel);
6750
6751 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6752 &pre_cac_chan);
6753 if (ret != 0)
6754 return ret;
6755
6756 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6757 * connection update should result in DBS mode
6758 */
6759 status = cds_update_and_wait_for_connection_update(
6760 ap_adapter->sessionId,
6761 pre_cac_chan,
6762 SIR_UPDATE_REASON_PRE_CAC);
6763 if (QDF_IS_STATUS_ERROR(status)) {
6764 hdd_err("error in moving to DBS mode");
6765 return -EINVAL;
6766 }
6767
6768 hdd_debug("starting pre cac SAP adapter");
6769
6770 /* Starting a SAP adapter:
6771 * Instead of opening an adapter, we could just do a SME open session
6772 * for AP type. But, start BSS would still need an adapter.
6773 * So, this option is not taken.
6774 *
6775 * hdd open adapter is going to register this precac interface with
6776 * user space. This interface though exposed to user space will be in
6777 * DOWN state. Consideration was done to avoid this registration to the
6778 * user space. But, as part of SAP operations multiple events are sent
6779 * to user space. Some of these events received from unregistered
6780 * interface was causing crashes. So, retaining the registration.
6781 *
6782 * So, this interface would remain registered and will remain in DOWN
6783 * state for the CAC duration. We will add notes in the feature
6784 * announcement to not use this temporary interface for any activity
6785 * from user space.
6786 */
6787 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6788 wlan_hdd_get_intf_addr(hdd_ctx),
6789 NET_NAME_UNKNOWN, true);
6790 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306791 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306792 return -EINVAL;
6793 }
6794
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306795 /*
6796 * This interface is internally created by the driver. So, no interface
6797 * up comes for this interface from user space and hence starting
6798 * the adapter internally.
6799 */
6800 if (hdd_start_adapter(pre_cac_adapter)) {
6801 hdd_err("error starting the pre cac adapter");
6802 goto close_pre_cac_adapter;
6803 }
6804
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306805 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6806
6807 wiphy = hdd_ctx->wiphy;
6808 dev = pre_cac_adapter->dev;
6809
6810 /* Since this is only a dummy interface lets us use the IEs from the
6811 * other active SAP interface. In regular scenarios, these IEs would
6812 * come from the user space entity
6813 */
6814 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6815 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6816 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6817 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306818 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306819 }
6820 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6821 ap_adapter->sessionCtx.ap.beacon,
6822 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6823 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6824 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6825 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6826 ap_adapter->sessionCtx.ap.sapConfig.authType;
6827
6828 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6829 * to operate on the same bandwidth as that of the 2.4GHz operations.
6830 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6831 */
6832 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6833 case CH_WIDTH_20MHZ:
6834 channel_type = NL80211_CHAN_HT20;
6835 break;
6836 case CH_WIDTH_40MHZ:
6837 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6838 ap_adapter->sessionCtx.ap.sapConfig.channel)
6839 channel_type = NL80211_CHAN_HT40PLUS;
6840 else
6841 channel_type = NL80211_CHAN_HT40MINUS;
6842 break;
6843 default:
6844 channel_type = NL80211_CHAN_NO_HT;
6845 break;
6846 }
6847
6848 freq = cds_chan_to_freq(pre_cac_chan);
6849 chan = __ieee80211_get_channel(wiphy, freq);
6850 if (!chan) {
6851 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306852 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306853 }
6854
6855 cfg80211_chandef_create(&chandef, chan, channel_type);
6856
6857 hdd_debug("orig width:%d channel_type:%d freq:%d",
6858 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6859 channel_type, freq);
6860
6861 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6862 if (0 != ret) {
6863 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306864 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306865 }
6866
6867 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6868 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6869 eHIDDEN_SSID_NOT_IN_USE, false);
6870 if (QDF_IS_STATUS_ERROR(status)) {
6871 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306872 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306873 }
6874
6875 /*
6876 * The pre cac status is set here. But, it would not be reset explicitly
6877 * anywhere, since after the pre cac success/failure, the pre cac
6878 * adapter itself would be removed.
6879 */
6880 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6881 if (0 != ret) {
6882 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306883 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306884 }
6885
6886 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6887 hdd_ap_ctx->operatingChannel);
6888 if (0 != ret) {
6889 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306890 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306891 }
6892
6893 ap_adapter->pre_cac_chan = pre_cac_chan;
6894
6895 return 0;
6896
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306897stop_close_pre_cac_adapter:
6898 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306899 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6900 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306901close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306902 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6903 return -EINVAL;
6904}
6905
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306906/**
6907 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6908 *
6909 * Return: None
6910 */
6911void hdd_init_bpf_completion(void)
6912{
6913 init_completion(&bpf_context.completion);
6914}
6915
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306916static const struct nla_policy
6917wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6918 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6919};
6920
Agrawal Ashish65634612016-08-18 13:24:32 +05306921static const struct nla_policy
6922wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
6923 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
6924 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
6925};
6926
6927/**
6928 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
6929 * @wiphy: Pointer to wireless phy
6930 * @wdev: Pointer to wireless device
6931 * @data: Pointer to data
6932 * @data_len: Length of @data
6933 *
6934 * This function parses the incoming NL vendor command data attributes and
6935 * updates the SAP context about channel_hint and DFS mode.
6936 * If channel_hint is set, SAP will choose that channel
6937 * as operating channel.
6938 *
6939 * If DFS mode is enabled, driver will include DFS channels
6940 * in ACS else driver will skip DFS channels.
6941 *
6942 * Return: 0 on success, negative errno on failure
6943 */
6944static int
6945__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6946 struct wireless_dev *wdev,
6947 const void *data, int data_len)
6948{
6949 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6950 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
6951 int ret;
6952 struct acs_dfs_policy *acs_policy;
6953 int mode = DFS_MODE_NONE;
6954 int channel_hint = 0;
6955
6956 ENTER_DEV(wdev->netdev);
6957
6958 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6959 hdd_err("Command not allowed in FTM mode");
6960 return -EINVAL;
6961 }
6962
6963 ret = wlan_hdd_validate_context(hdd_ctx);
6964 if (0 != ret)
6965 return ret;
6966
6967 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
6968 data, data_len,
6969 wlan_hdd_set_acs_dfs_config_policy)) {
6970 hdd_err("invalid attr");
6971 return -EINVAL;
6972 }
6973
6974 acs_policy = &hdd_ctx->acs_policy;
6975 /*
6976 * SCM sends this attribute to restrict SAP from choosing
6977 * DFS channels from ACS.
6978 */
6979 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
6980 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
6981
6982 if (!IS_DFS_MODE_VALID(mode)) {
6983 hdd_err("attr acs dfs mode is not valid");
6984 return -EINVAL;
6985 }
6986 acs_policy->acs_dfs_mode = mode;
6987
6988 /*
6989 * SCM sends this attribute to provide an active channel,
6990 * to skip redundant ACS between drivers, and save driver start up time
6991 */
6992 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
6993 channel_hint = nla_get_u8(
6994 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
6995
6996 if (!IS_CHANNEL_VALID(channel_hint)) {
6997 hdd_err("acs channel is not valid");
6998 return -EINVAL;
6999 }
7000 acs_policy->acs_channel = channel_hint;
7001
7002 return 0;
7003}
7004
7005/**
7006 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7007 * @wiphy: wiphy structure pointer
7008 * @wdev: Wireless device structure pointer
7009 * @data: Pointer to the data received
7010 * @data_len: Length of @data
7011 *
7012 * This function parses the incoming NL vendor command data attributes and
7013 * updates the SAP context about channel_hint and DFS mode.
7014 *
7015 * Return: 0 on success; errno on failure
7016 */
7017static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7018 struct wireless_dev *wdev,
7019 const void *data, int data_len)
7020{
7021 int ret;
7022
7023 cds_ssr_protect(__func__);
7024 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7025 cds_ssr_unprotect(__func__);
7026
7027 return ret;
7028}
7029
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307030/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307031 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7032 * @mode : cfg80211 dfs mode
7033 *
7034 * Return: return csr sta roam dfs mode else return NONE
7035 */
7036static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7037 enum dfs_mode mode)
7038{
7039 switch (mode) {
7040 case DFS_MODE_ENABLE:
7041 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7042 break;
7043 case DFS_MODE_DISABLE:
7044 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7045 break;
7046 case DFS_MODE_DEPRIORITIZE:
7047 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7048 break;
7049 default:
7050 hdd_err("STA Roam policy dfs mode is NONE");
7051 return CSR_STA_ROAM_POLICY_NONE;
7052 }
7053}
7054
7055static const struct nla_policy
7056wlan_hdd_set_sta_roam_config_policy[
7057QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7058 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7059 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7060};
7061
7062/**
7063 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7064 * for station connection or roaming.
7065 * @wiphy: Pointer to wireless phy
7066 * @wdev: Pointer to wireless device
7067 * @data: Pointer to data
7068 * @data_len: Length of @data
7069 *
7070 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7071 * channels needs to be skipped in scanning or not.
7072 * If dfs_mode is disabled, driver will not scan DFS channels.
7073 * If skip_unsafe_channels is set, driver will skip unsafe channels
7074 * in Scanning.
7075 *
7076 * Return: 0 on success, negative errno on failure
7077 */
7078static int
7079__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7080 struct wireless_dev *wdev,
7081 const void *data, int data_len)
7082{
7083 struct net_device *dev = wdev->netdev;
7084 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7085 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7086 struct nlattr *tb[
7087 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7088 int ret;
7089 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7090 enum dfs_mode mode = DFS_MODE_NONE;
7091 bool skip_unsafe_channels = false;
7092 QDF_STATUS status;
7093
7094 ENTER_DEV(dev);
7095
7096 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7097 hdd_err("Command not allowed in FTM mode");
7098 return -EINVAL;
7099 }
7100
7101 ret = wlan_hdd_validate_context(hdd_ctx);
7102 if (0 != ret)
7103 return ret;
7104 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7105 data, data_len,
7106 wlan_hdd_set_sta_roam_config_policy)) {
7107 hdd_err("invalid attr");
7108 return -EINVAL;
7109 }
7110 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7111 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7112 if (!IS_DFS_MODE_VALID(mode)) {
7113 hdd_err("attr sta roam dfs mode policy is not valid");
7114 return -EINVAL;
7115 }
7116
7117 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7118
7119 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7120 skip_unsafe_channels = nla_get_u8(
7121 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7122
7123 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7124 skip_unsafe_channels, adapter->sessionId);
7125
7126 if (!QDF_IS_STATUS_SUCCESS(status)) {
7127 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7128 return -EINVAL;
7129 }
7130 return 0;
7131}
7132
7133/**
7134 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7135 * connection and roaming for station.
7136 * @wiphy: wiphy structure pointer
7137 * @wdev: Wireless device structure pointer
7138 * @data: Pointer to the data received
7139 * @data_len: Length of @data
7140 *
7141 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7142 * channels needs to be skipped in scanning or not.
7143 * If dfs_mode is disabled, driver will not scan DFS channels.
7144 * If skip_unsafe_channels is set, driver will skip unsafe channels
7145 * in Scanning.
7146 * Return: 0 on success; errno on failure
7147 */
7148static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7149 struct wireless_dev *wdev,
7150 const void *data, int data_len)
7151{
7152 int ret;
7153
7154 cds_ssr_protect(__func__);
7155 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7156 cds_ssr_unprotect(__func__);
7157
7158 return ret;
7159}
7160
Agrawal Ashish467dde42016-09-08 18:44:22 +05307161#ifdef FEATURE_WLAN_CH_AVOID
7162/**
7163 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7164 * is on unsafe channel.
7165 * @wiphy: wiphy structure pointer
7166 * @wdev: Wireless device structure pointer
7167 * @data: Pointer to the data received
7168 * @data_len: Length of @data
7169 *
7170 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7171 * on any of unsafe channels.
7172 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7173 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7174 *
7175 * Return: 0 on success; errno on failure
7176 */
7177static int
7178__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7179 struct wireless_dev *wdev,
7180 const void *data, int data_len)
7181{
7182 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7183 int ret;
7184 uint16_t unsafe_channel_count;
7185 int unsafe_channel_index;
7186 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7187
7188 ENTER_DEV(wdev->netdev);
7189
7190 if (!qdf_ctx) {
7191 cds_err("qdf_ctx is NULL");
7192 return -EINVAL;
7193 }
7194
7195 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7196 hdd_err("Command not allowed in FTM mode");
7197 return -EINVAL;
7198 }
7199
7200 ret = wlan_hdd_validate_context(hdd_ctx);
7201 if (0 != ret)
7202 return ret;
7203 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7204 &(hdd_ctx->unsafe_channel_count),
7205 sizeof(hdd_ctx->unsafe_channel_list));
7206
7207 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7208 (uint16_t)NUM_CHANNELS);
7209 for (unsafe_channel_index = 0;
7210 unsafe_channel_index < unsafe_channel_count;
7211 unsafe_channel_index++) {
7212 hdd_info("Channel %d is not safe",
7213 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7214 }
7215 hdd_unsafe_channel_restart_sap(hdd_ctx);
7216 return 0;
7217}
7218
7219/**
7220 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7221 * is on unsafe channel.
7222 * @wiphy: wiphy structure pointer
7223 * @wdev: Wireless device structure pointer
7224 * @data: Pointer to the data received
7225 * @data_len: Length of @data
7226 *
7227 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7228 * on any of unsafe channels.
7229 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7230 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7231 *
7232 * Return: 0 on success; errno on failure
7233 */
7234static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7235 struct wireless_dev *wdev,
7236 const void *data, int data_len)
7237{
7238 int ret;
7239
7240 cds_ssr_protect(__func__);
7241 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7242 cds_ssr_unprotect(__func__);
7243
7244 return ret;
7245}
7246
7247#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307248/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307249 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7250 * SAP is on unsafe channel.
7251 * @wiphy: wiphy structure pointer
7252 * @wdev: Wireless device structure pointer
7253 * @data: Pointer to the data received
7254 * @data_len: Length of @data
7255 *
7256 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7257 * driver.
7258 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7259 * will initiate restart of sap.
7260 *
7261 * Return: 0 on success; errno on failure
7262 */
7263static int
7264__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7265 struct wireless_dev *wdev,
7266 const void *data, int data_len)
7267{
7268 struct net_device *ndev = wdev->netdev;
7269 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7270 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7271 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7272 uint8_t config_channel = 0;
7273 hdd_ap_ctx_t *ap_ctx;
7274 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307275 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307276
7277 ENTER();
7278
7279 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007280 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307281 return -EINVAL;
7282 }
7283
7284 ret = wlan_hdd_validate_context(hdd_ctx);
7285 if (0 != ret)
7286 return -EINVAL;
7287
7288 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7289 data, data_len,
7290 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007291 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307292 return -EINVAL;
7293 }
7294
7295 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7296 if (!test_bit(SOFTAP_BSS_STARTED,
7297 &hostapd_adapter->event_flags)) {
7298 hdd_err("SAP is not started yet. Restart sap will be invalid");
7299 return -EINVAL;
7300 }
7301
7302 config_channel =
7303 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7304
7305 if (!((IS_24G_CH(config_channel)) ||
7306 (IS_5G_CH(config_channel)))) {
7307 hdd_err("Channel %d is not valid to restart SAP",
7308 config_channel);
7309 return -ENOTSUPP;
7310 }
7311
7312 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7313 ap_ctx->sapConfig.channel = config_channel;
7314 ap_ctx->sapConfig.ch_params.ch_width =
7315 ap_ctx->sapConfig.ch_width_orig;
7316
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007317 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307318 ap_ctx->sapConfig.sec_ch,
7319 &ap_ctx->sapConfig.ch_params);
7320
7321 cds_restart_sap(hostapd_adapter);
7322 }
7323
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307324 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7325 uint32_t freq_len, i;
7326 uint32_t *freq;
7327 uint8_t chans[QDF_MAX_NUM_CHAN];
7328
7329 hdd_debug("setting mandatory freq/chan list");
7330
7331 freq_len = nla_len(
7332 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7333 sizeof(uint32_t);
7334
7335 if (freq_len > QDF_MAX_NUM_CHAN) {
7336 hdd_err("insufficient space to hold channels");
7337 return -ENOMEM;
7338 }
7339
7340 freq = nla_data(
7341 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7342
7343 hdd_debug("freq_len=%d", freq_len);
7344
7345 for (i = 0; i < freq_len; i++) {
7346 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7347 hdd_debug("freq[%d]=%d", i, freq[i]);
7348 }
7349
7350 status = cds_set_sap_mandatory_channels(chans, freq_len);
7351 if (QDF_IS_STATUS_ERROR(status))
7352 return -EINVAL;
7353 }
7354
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307355 return 0;
7356}
7357
7358/**
7359 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7360 * @wiphy: wiphy structure pointer
7361 * @wdev: Wireless device structure pointer
7362 * @data: Pointer to the data received
7363 * @data_len: Length of @data
7364 *
7365 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7366 * driver.
7367 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7368 * will initiate restart of sap.
7369 *
7370 * Return: 0 on success; errno on failure
7371 */
7372static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7373 struct wireless_dev *wdev,
7374 const void *data, int data_len)
7375{
7376 int ret;
7377
7378 cds_ssr_protect(__func__);
7379 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7380 wdev, data, data_len);
7381 cds_ssr_unprotect(__func__);
7382
7383 return ret;
7384}
7385
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307386#undef BPF_INVALID
7387#undef BPF_SET_RESET
7388#undef BPF_VERSION
7389#undef BPF_ID
7390#undef BPF_PACKET_SIZE
7391#undef BPF_CURRENT_OFFSET
7392#undef BPF_PROGRAM
7393#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307394
7395/**
7396 * define short names for the global vendor params
7397 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7398 */
7399#define PARAM_TOTAL_CMD_EVENT_WAKE \
7400 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7401#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7402 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7403#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7404 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7405#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7406 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7407#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7408 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7409#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7410 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7411#define PARAM_TOTAL_RX_DATA_WAKE \
7412 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7413#define PARAM_RX_UNICAST_CNT \
7414 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7415#define PARAM_RX_MULTICAST_CNT \
7416 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7417#define PARAM_RX_BROADCAST_CNT \
7418 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7419#define PARAM_ICMP_PKT \
7420 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7421#define PARAM_ICMP6_PKT \
7422 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7423#define PARAM_ICMP6_RA \
7424 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7425#define PARAM_ICMP6_NA \
7426 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7427#define PARAM_ICMP6_NS \
7428 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7429#define PARAM_ICMP4_RX_MULTICAST_CNT \
7430 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7431#define PARAM_ICMP6_RX_MULTICAST_CNT \
7432 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7433#define PARAM_OTHER_RX_MULTICAST_CNT \
7434 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7435
7436
7437/**
7438 * hdd_send_wakelock_stats() - API to send wakelock stats
7439 * @ctx: context to be passed to callback
7440 * @data: data passed to callback
7441 *
7442 * This function is used to send wake lock stats to HAL layer
7443 *
7444 * Return: 0 on success, error number otherwise.
7445 */
7446static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7447 const struct sir_wake_lock_stats *data)
7448{
7449 struct sk_buff *skb;
7450 uint32_t nl_buf_len;
7451 uint32_t total_rx_data_wake, rx_multicast_cnt;
7452 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307453 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307454
7455 ENTER();
7456
7457 nl_buf_len = NLMSG_HDRLEN;
7458 nl_buf_len +=
7459 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7460 (NLMSG_HDRLEN + sizeof(uint32_t));
7461
7462 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7463
7464 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007465 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307466 return -ENOMEM;
7467 }
7468
Jeff Johnson64943bd2016-08-23 13:14:06 -07007469 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307470 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007471 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307472 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007473 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307474 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007475 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307476 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007477 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307478 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007479 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307480 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007481 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307482 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007483 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7484 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307485 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307486
7487 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307488 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307489
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307490 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307491 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307492
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307493 rx_multicast_cnt =
7494 data->wow_ipv4_mcast_wake_up_count +
7495 ipv6_rx_multicast_addr_cnt;
7496
7497 total_rx_data_wake =
7498 data->wow_ucast_wake_up_count +
7499 data->wow_bcast_wake_up_count +
7500 rx_multicast_cnt;
7501
7502 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7503 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7504 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7505 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7506 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7507 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7508 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7509 total_rx_data_wake) ||
7510 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7511 data->wow_ucast_wake_up_count) ||
7512 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7513 rx_multicast_cnt) ||
7514 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7515 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307516 nla_put_u32(skb, PARAM_ICMP_PKT,
7517 data->wow_icmpv4_count) ||
7518 nla_put_u32(skb, PARAM_ICMP6_PKT,
7519 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307520 nla_put_u32(skb, PARAM_ICMP6_RA,
7521 data->wow_ipv6_mcast_ra_stats) ||
7522 nla_put_u32(skb, PARAM_ICMP6_NA,
7523 data->wow_ipv6_mcast_na_stats) ||
7524 nla_put_u32(skb, PARAM_ICMP6_NS,
7525 data->wow_ipv6_mcast_ns_stats) ||
7526 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7527 data->wow_ipv4_mcast_wake_up_count) ||
7528 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7529 ipv6_rx_multicast_addr_cnt) ||
7530 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007531 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307532 goto nla_put_failure;
7533 }
7534
7535 cfg80211_vendor_cmd_reply(skb);
7536
7537 EXIT();
7538 return 0;
7539
7540nla_put_failure:
7541 kfree_skb(skb);
7542 return -EINVAL;
7543}
7544
7545/**
7546 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7547 * @wiphy: wiphy pointer
7548 * @wdev: pointer to struct wireless_dev
7549 * @data: pointer to incoming NL vendor data
7550 * @data_len: length of @data
7551 *
7552 * This function parses the incoming NL vendor command data attributes and
7553 * invokes the SME Api and blocks on a completion variable.
7554 * WMA copies required data and invokes callback
7555 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7556 *
7557 * Return: 0 on success; error number otherwise.
7558 */
7559static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7560 struct wireless_dev *wdev,
7561 const void *data,
7562 int data_len)
7563{
7564 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7565 int status, ret;
7566 struct sir_wake_lock_stats wake_lock_stats;
7567 QDF_STATUS qdf_status;
7568
7569 ENTER();
7570
7571 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007572 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307573 return -EINVAL;
7574 }
7575
7576 status = wlan_hdd_validate_context(hdd_ctx);
7577 if (0 != status)
7578 return -EINVAL;
7579
7580 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7581 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007582 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307583 return -EINVAL;
7584 }
7585
7586 ret = hdd_send_wakelock_stats(hdd_ctx,
7587 &wake_lock_stats);
7588 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007589 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307590
7591 EXIT();
7592 return ret;
7593}
7594
7595/**
7596 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7597 * @wiphy: wiphy pointer
7598 * @wdev: pointer to struct wireless_dev
7599 * @data: pointer to incoming NL vendor data
7600 * @data_len: length of @data
7601 *
7602 * This function parses the incoming NL vendor command data attributes and
7603 * invokes the SME Api and blocks on a completion variable.
7604 * WMA copies required data and invokes callback
7605 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7606 *
7607 * Return: 0 on success; error number otherwise.
7608 */
7609static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7610 struct wireless_dev *wdev,
7611 const void *data, int data_len)
7612{
7613 int ret;
7614
7615 cds_ssr_protect(__func__);
7616 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7617 data_len);
7618 cds_ssr_protect(__func__);
7619
7620 return ret;
7621}
7622
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307623/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307624 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7625 * @wiphy: wiphy structure pointer
7626 * @wdev: Wireless device structure pointer
7627 * @data: Pointer to the data received
7628 * @data_len: Length of @data
7629 *
7630 * This function reads wmi max bus size and fill in the skb with
7631 * NL attributes and send up the NL event.
7632 * Return: 0 on success; errno on failure
7633 */
7634static int
7635__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7636 struct wireless_dev *wdev,
7637 const void *data, int data_len)
7638{
7639 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7640 int ret_val;
7641 struct sk_buff *skb;
7642 uint32_t nl_buf_len;
7643
7644 ENTER();
7645
7646 ret_val = wlan_hdd_validate_context(hdd_ctx);
7647 if (ret_val)
7648 return ret_val;
7649
7650 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7651 hdd_err("Command not allowed in FTM mode");
7652 return -EINVAL;
7653 }
7654
7655 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7656
7657 nl_buf_len = NLMSG_HDRLEN;
7658 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7659
7660 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7661 if (!skb) {
7662 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7663 return -ENOMEM;
7664 }
7665
7666 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7667 hdd_ctx->wmi_max_len)) {
7668 hdd_err("nla put failure");
7669 goto nla_put_failure;
7670 }
7671
7672 cfg80211_vendor_cmd_reply(skb);
7673
7674 EXIT();
7675
7676 return 0;
7677
7678nla_put_failure:
7679 kfree_skb(skb);
7680 return -EINVAL;
7681}
7682
7683/**
7684 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7685 * @wiphy: wiphy structure pointer
7686 * @wdev: Wireless device structure pointer
7687 * @data: Pointer to the data received
7688 * @data_len: Length of @data
7689 *
7690 * Return: 0 on success; errno on failure
7691 */
7692static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7693 struct wireless_dev *wdev,
7694 const void *data, int data_len)
7695{
7696 int ret;
7697
7698 cds_ssr_protect(__func__);
7699 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7700 cds_ssr_unprotect(__func__);
7701
7702 return ret;
7703}
7704
7705/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307706 *__wlan_hdd_cfg80211_setband() - set band
7707 * @wiphy: Pointer to wireless phy
7708 * @wdev: Pointer to wireless device
7709 * @data: Pointer to data
7710 * @data_len: Length of @data
7711 *
7712 * Return: 0 on success, negative errno on failure
7713 */
7714static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7715 struct wireless_dev *wdev,
7716 const void *data, int data_len)
7717{
7718 struct net_device *dev = wdev->netdev;
7719 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7720 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7721 int ret;
7722 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7723 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7724
7725 ENTER();
7726
7727 ret = wlan_hdd_validate_context(hdd_ctx);
7728 if (ret)
7729 return ret;
7730
7731 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7732 hdd_err(FL("Invalid ATTR"));
7733 return -EINVAL;
7734 }
7735
7736 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7737 hdd_err(FL("attr SETBAND_VALUE failed"));
7738 return -EINVAL;
7739 }
7740
7741 ret = hdd_set_band(dev,
7742 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7743
7744 EXIT();
7745 return ret;
7746}
7747
7748/**
7749 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7750 * @wiphy: wiphy structure pointer
7751 * @wdev: Wireless device structure pointer
7752 * @data: Pointer to the data received
7753 * @data_len: Length of @data
7754 *
7755 * Return: 0 on success; errno on failure
7756 */
7757static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7758 struct wireless_dev *wdev,
7759 const void *data, int data_len)
7760{
7761 int ret;
7762
7763 cds_ssr_protect(__func__);
7764 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7765 cds_ssr_unprotect(__func__);
7766
7767 return ret;
7768}
7769
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307770static const struct
7771nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7772 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7773 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7774 .len = QDF_MAC_ADDR_SIZE},
7775};
7776
7777/**
7778 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7779 * @wiphy: Pointer to wireless phy
7780 * @wdev: Pointer to wireless device
7781 * @data: Pointer to data
7782 * @data_len: Length of @data
7783 *
7784 * This function is used to enable/disable roaming using vendor commands
7785 *
7786 * Return: 0 on success, negative errno on failure
7787 */
7788static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7789 struct wireless_dev *wdev,
7790 const void *data, int data_len)
7791{
7792 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7793 struct net_device *dev = wdev->netdev;
7794 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7795 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7796 uint32_t is_fast_roam_enabled;
7797 int ret;
7798
7799 ENTER_DEV(dev);
7800
7801 ret = wlan_hdd_validate_context(hdd_ctx);
7802 if (0 != ret)
7803 return ret;
7804
7805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7806 hdd_err("Command not allowed in FTM mode");
7807 return -EINVAL;
7808 }
7809
7810 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7811 qca_wlan_vendor_attr);
7812 if (ret) {
7813 hdd_err("Invalid ATTR");
7814 return -EINVAL;
7815 }
7816
7817 /* Parse and fetch Enable flag */
7818 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7819 hdd_err("attr enable failed");
7820 return -EINVAL;
7821 }
7822
7823 is_fast_roam_enabled = nla_get_u32(
7824 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7825 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7826
7827 /* Update roaming */
7828 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7829 is_fast_roam_enabled);
7830 if (ret)
7831 hdd_err("sme_config_fast_roaming failed");
7832 EXIT();
7833 return ret;
7834}
7835
7836/**
7837 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7838 * @wiphy: Pointer to wireless phy
7839 * @wdev: Pointer to wireless device
7840 * @data: Pointer to data
7841 * @data_len: Length of @data
7842 *
7843 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7844 *
7845 * Return: 0 on success, negative errno on failure
7846 */
7847static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7848 struct wireless_dev *wdev,
7849 const void *data, int data_len)
7850{
7851 int ret;
7852
7853 cds_ssr_protect(__func__);
7854 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7855 cds_ssr_unprotect(__func__);
7856
7857 return ret;
7858}
7859
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007860const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7861 {
7862 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7863 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7864 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307865 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007866 .doit = is_driver_dfs_capable
7867 },
7868
7869#ifdef WLAN_FEATURE_NAN
7870 {
7871 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7872 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7873 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7874 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7875 .doit = wlan_hdd_cfg80211_nan_request
7876 },
7877#endif
7878
7879#ifdef WLAN_FEATURE_STATS_EXT
7880 {
7881 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7882 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7883 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7884 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7885 .doit = wlan_hdd_cfg80211_stats_ext_request
7886 },
7887#endif
7888#ifdef FEATURE_WLAN_EXTSCAN
7889 {
7890 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7891 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7892 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7893 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7894 .doit = wlan_hdd_cfg80211_extscan_start
7895 },
7896 {
7897 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7898 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7899 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7900 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7901 .doit = wlan_hdd_cfg80211_extscan_stop
7902 },
7903 {
7904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7905 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7907 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7908 },
7909 {
7910 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7911 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7912 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7913 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7914 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7915 },
7916 {
7917 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7918 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7920 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7921 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7922 },
7923 {
7924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7927 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7928 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7929 },
7930 {
7931 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7932 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7934 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7935 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7936 },
7937 {
7938 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7939 .info.subcmd =
7940 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7941 .flags =
7942 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7943 WIPHY_VENDOR_CMD_NEED_RUNNING,
7944 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7945 },
7946 {
7947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7948 .info.subcmd =
7949 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7950 .flags =
7951 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7952 WIPHY_VENDOR_CMD_NEED_RUNNING,
7953 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7954 },
7955 {
7956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7957 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7958 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7959 WIPHY_VENDOR_CMD_NEED_NETDEV |
7960 WIPHY_VENDOR_CMD_NEED_RUNNING,
7961 .doit = wlan_hdd_cfg80211_set_epno_list
7962 },
7963#endif /* FEATURE_WLAN_EXTSCAN */
7964
7965#ifdef WLAN_FEATURE_LINK_LAYER_STATS
7966 {
7967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7968 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
7969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7970 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7971 .doit = wlan_hdd_cfg80211_ll_stats_clear
7972 },
7973
7974 {
7975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
7977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7978 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7979 .doit = wlan_hdd_cfg80211_ll_stats_set
7980 },
7981
7982 {
7983 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7984 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
7985 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7986 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7987 .doit = wlan_hdd_cfg80211_ll_stats_get
7988 },
7989#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
7990#ifdef FEATURE_WLAN_TDLS
7991 {
7992 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7993 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
7994 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7995 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7996 .doit = wlan_hdd_cfg80211_exttdls_enable
7997 },
7998 {
7999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8002 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8003 .doit = wlan_hdd_cfg80211_exttdls_disable
8004 },
8005 {
8006 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8007 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8008 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8009 .doit = wlan_hdd_cfg80211_exttdls_get_status
8010 },
8011#endif
8012 {
8013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8016 .doit = wlan_hdd_cfg80211_get_supported_features
8017 },
8018 {
8019 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8020 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8021 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8022 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8023 },
8024 {
8025 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8026 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8027 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308028 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008029 },
8030 {
8031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8032 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8033 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8034 WIPHY_VENDOR_CMD_NEED_NETDEV,
8035 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8036 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008037 {
8038 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8039 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8040 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8041 WIPHY_VENDOR_CMD_NEED_NETDEV,
8042 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8043 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008044 {
8045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8048 WIPHY_VENDOR_CMD_NEED_NETDEV |
8049 WIPHY_VENDOR_CMD_NEED_RUNNING,
8050 .doit = hdd_cfg80211_get_station_cmd
8051 },
8052 {
8053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8056 WIPHY_VENDOR_CMD_NEED_NETDEV |
8057 WIPHY_VENDOR_CMD_NEED_RUNNING,
8058 .doit = wlan_hdd_cfg80211_do_acs
8059 },
8060
8061 {
8062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8065 WIPHY_VENDOR_CMD_NEED_NETDEV,
8066 .doit = wlan_hdd_cfg80211_get_features
8067 },
8068#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8069 {
8070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8071 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8072 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8073 WIPHY_VENDOR_CMD_NEED_NETDEV |
8074 WIPHY_VENDOR_CMD_NEED_RUNNING,
8075 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8076 },
8077#endif
8078#ifdef FEATURE_WLAN_EXTSCAN
8079 {
8080 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8081 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8082 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8083 WIPHY_VENDOR_CMD_NEED_NETDEV |
8084 WIPHY_VENDOR_CMD_NEED_RUNNING,
8085 .doit = wlan_hdd_cfg80211_set_passpoint_list
8086 },
8087 {
8088 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8089 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8090 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8091 WIPHY_VENDOR_CMD_NEED_NETDEV |
8092 WIPHY_VENDOR_CMD_NEED_RUNNING,
8093 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8094 },
8095 {
8096 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8097 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8098 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8099 WIPHY_VENDOR_CMD_NEED_NETDEV |
8100 WIPHY_VENDOR_CMD_NEED_RUNNING,
8101 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8102 },
8103 {
8104 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8105 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8106 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8107 WIPHY_VENDOR_CMD_NEED_NETDEV |
8108 WIPHY_VENDOR_CMD_NEED_RUNNING,
8109 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8110 },
8111#endif /* FEATURE_WLAN_EXTSCAN */
8112 {
8113 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8114 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8115 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8116 WIPHY_VENDOR_CMD_NEED_NETDEV,
8117 .doit = wlan_hdd_cfg80211_get_wifi_info
8118 },
8119 {
8120 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8121 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8122 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8123 WIPHY_VENDOR_CMD_NEED_NETDEV |
8124 WIPHY_VENDOR_CMD_NEED_RUNNING,
8125 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8126 },
8127 {
8128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8131 WIPHY_VENDOR_CMD_NEED_NETDEV,
8132 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8133 },
8134 {
8135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8138 WIPHY_VENDOR_CMD_NEED_NETDEV,
8139 .doit = wlan_hdd_cfg80211_wifi_logger_start
8140 },
8141 {
8142 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8143 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8144 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8145 WIPHY_VENDOR_CMD_NEED_NETDEV,
8146 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8147 },
8148 {
8149 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8150 .info.subcmd =
8151 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8152 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8153 WIPHY_VENDOR_CMD_NEED_NETDEV |
8154 WIPHY_VENDOR_CMD_NEED_RUNNING,
8155 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8156 },
8157 {
8158 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8159 .info.subcmd =
8160 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8161 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8162 WIPHY_VENDOR_CMD_NEED_NETDEV |
8163 WIPHY_VENDOR_CMD_NEED_RUNNING,
8164 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8165 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008166#ifdef WLAN_FEATURE_TSF
8167 {
8168 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8169 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8170 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8171 WIPHY_VENDOR_CMD_NEED_NETDEV |
8172 WIPHY_VENDOR_CMD_NEED_RUNNING,
8173 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8174 },
8175#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008176#ifdef FEATURE_WLAN_TDLS
8177 {
8178 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8179 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8180 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8181 WIPHY_VENDOR_CMD_NEED_NETDEV |
8182 WIPHY_VENDOR_CMD_NEED_RUNNING,
8183 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8184 },
8185#endif
8186#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8187 {
8188 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8189 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8190 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8191 WIPHY_VENDOR_CMD_NEED_NETDEV |
8192 WIPHY_VENDOR_CMD_NEED_RUNNING,
8193 .doit = wlan_hdd_cfg80211_offloaded_packets
8194 },
8195#endif
8196 {
8197 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8198 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8199 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8200 WIPHY_VENDOR_CMD_NEED_NETDEV |
8201 WIPHY_VENDOR_CMD_NEED_RUNNING,
8202 .doit = wlan_hdd_cfg80211_monitor_rssi
8203 },
8204 {
8205 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308206 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8207 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8208 WIPHY_VENDOR_CMD_NEED_NETDEV |
8209 WIPHY_VENDOR_CMD_NEED_RUNNING,
8210 .doit = wlan_hdd_cfg80211_set_ns_offload
8211 },
8212 {
8213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008214 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8215 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8216 WIPHY_VENDOR_CMD_NEED_NETDEV |
8217 WIPHY_VENDOR_CMD_NEED_RUNNING,
8218 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8219 },
8220#ifdef WLAN_FEATURE_MEMDUMP
8221 {
8222 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8223 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8224 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8225 WIPHY_VENDOR_CMD_NEED_NETDEV |
8226 WIPHY_VENDOR_CMD_NEED_RUNNING,
8227 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8228 },
8229#endif /* WLAN_FEATURE_MEMDUMP */
8230 {
8231 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8232 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8233 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8234 WIPHY_VENDOR_CMD_NEED_NETDEV |
8235 WIPHY_VENDOR_CMD_NEED_RUNNING,
8236 .doit = wlan_hdd_cfg80211_vendor_scan
8237 },
8238
8239 /* OCB commands */
8240 {
8241 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8242 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8243 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8244 WIPHY_VENDOR_CMD_NEED_NETDEV |
8245 WIPHY_VENDOR_CMD_NEED_RUNNING,
8246 .doit = wlan_hdd_cfg80211_ocb_set_config
8247 },
8248 {
8249 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8250 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8251 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8252 WIPHY_VENDOR_CMD_NEED_NETDEV |
8253 WIPHY_VENDOR_CMD_NEED_RUNNING,
8254 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8255 },
8256 {
8257 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8258 .info.subcmd =
8259 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8260 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8261 WIPHY_VENDOR_CMD_NEED_NETDEV |
8262 WIPHY_VENDOR_CMD_NEED_RUNNING,
8263 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8264 },
8265 {
8266 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8267 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8268 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8269 WIPHY_VENDOR_CMD_NEED_NETDEV |
8270 WIPHY_VENDOR_CMD_NEED_RUNNING,
8271 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8272 },
8273 {
8274 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8275 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8276 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8277 WIPHY_VENDOR_CMD_NEED_NETDEV |
8278 WIPHY_VENDOR_CMD_NEED_RUNNING,
8279 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8280 },
8281 {
8282 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8283 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8284 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8285 WIPHY_VENDOR_CMD_NEED_NETDEV |
8286 WIPHY_VENDOR_CMD_NEED_RUNNING,
8287 .doit = wlan_hdd_cfg80211_dcc_get_stats
8288 },
8289 {
8290 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8291 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8292 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8293 WIPHY_VENDOR_CMD_NEED_NETDEV |
8294 WIPHY_VENDOR_CMD_NEED_RUNNING,
8295 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8296 },
8297 {
8298 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8299 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8300 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8301 WIPHY_VENDOR_CMD_NEED_NETDEV |
8302 WIPHY_VENDOR_CMD_NEED_RUNNING,
8303 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8304 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308305 {
8306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8309 WIPHY_VENDOR_CMD_NEED_NETDEV |
8310 WIPHY_VENDOR_CMD_NEED_RUNNING,
8311 .doit = wlan_hdd_cfg80211_get_link_properties
8312 },
Peng Xu278d0122015-09-24 16:34:17 -07008313 {
Peng Xud2220962016-07-11 17:59:17 -07008314 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008315 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8316 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8317 WIPHY_VENDOR_CMD_NEED_NETDEV |
8318 WIPHY_VENDOR_CMD_NEED_RUNNING,
8319 .doit = wlan_hdd_cfg80211_set_ota_test
8320 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008321#ifdef FEATURE_LFR_SUBNET_DETECTION
8322 {
8323 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8324 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8325 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8326 WIPHY_VENDOR_CMD_NEED_NETDEV |
8327 WIPHY_VENDOR_CMD_NEED_RUNNING,
8328 .doit = wlan_hdd_cfg80211_set_gateway_params
8329 },
8330#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008331 {
Peng Xud2220962016-07-11 17:59:17 -07008332 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008333 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8334 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8335 WIPHY_VENDOR_CMD_NEED_NETDEV |
8336 WIPHY_VENDOR_CMD_NEED_RUNNING,
8337 .doit = wlan_hdd_cfg80211_txpower_scale
8338 },
8339 {
8340 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8341 .info.subcmd =
8342 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8343 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8344 WIPHY_VENDOR_CMD_NEED_NETDEV |
8345 WIPHY_VENDOR_CMD_NEED_RUNNING,
8346 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8347 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308348 {
8349 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8350 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8352 WIPHY_VENDOR_CMD_NEED_NETDEV |
8353 WIPHY_VENDOR_CMD_NEED_RUNNING,
8354 .doit = wlan_hdd_cfg80211_bpf_offload
8355 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308356 {
8357 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308358 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8359 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8360 WIPHY_VENDOR_CMD_NEED_NETDEV |
8361 WIPHY_VENDOR_CMD_NEED_RUNNING,
8362 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8363 },
8364 {
8365 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308366 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8367 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8368 WIPHY_VENDOR_CMD_NEED_NETDEV |
8369 WIPHY_VENDOR_CMD_NEED_RUNNING,
8370 .doit = wlan_hdd_cfg80211_sta_roam_policy
8371 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308372#ifdef FEATURE_WLAN_CH_AVOID
8373 {
8374 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8375 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8376 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8377 WIPHY_VENDOR_CMD_NEED_NETDEV |
8378 WIPHY_VENDOR_CMD_NEED_RUNNING,
8379 .doit = wlan_hdd_cfg80211_avoid_freq
8380 },
8381#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308382 {
8383 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308384 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8385 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8386 WIPHY_VENDOR_CMD_NEED_NETDEV |
8387 WIPHY_VENDOR_CMD_NEED_RUNNING,
8388 .doit = wlan_hdd_cfg80211_sap_configuration_set
8389 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008390 {
Peng Xu4225c152016-07-14 21:18:14 -07008391 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008392 .info.subcmd =
8393 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8394 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8395 WIPHY_VENDOR_CMD_NEED_NETDEV |
8396 WIPHY_VENDOR_CMD_NEED_RUNNING,
8397 .doit = wlan_hdd_cfg80211_p2p_lo_start
8398 },
8399 {
8400 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8401 .info.subcmd =
8402 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8403 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8404 WIPHY_VENDOR_CMD_NEED_NETDEV |
8405 WIPHY_VENDOR_CMD_NEED_RUNNING,
8406 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8407 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308408 {
8409 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8410 .info.subcmd =
8411 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8412 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8413 WIPHY_VENDOR_CMD_NEED_NETDEV |
8414 WIPHY_VENDOR_CMD_NEED_RUNNING,
8415 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8416 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008417#ifdef WLAN_FEATURE_NAN_DATAPATH
8418 {
8419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8422 WIPHY_VENDOR_CMD_NEED_NETDEV |
8423 WIPHY_VENDOR_CMD_NEED_RUNNING,
8424 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8425 },
8426#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308427 {
8428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8429 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8431 WIPHY_VENDOR_CMD_NEED_NETDEV |
8432 WIPHY_VENDOR_CMD_NEED_RUNNING,
8433 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8434 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308435 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308436 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8437 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8438 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8439 WIPHY_VENDOR_CMD_NEED_NETDEV |
8440 WIPHY_VENDOR_CMD_NEED_RUNNING,
8441 .doit = wlan_hdd_cfg80211_get_bus_size
8442 },
8443 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308444 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8445 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8446 WIPHY_VENDOR_CMD_NEED_NETDEV |
8447 WIPHY_VENDOR_CMD_NEED_RUNNING,
8448 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308449 },
8450 {
8451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8454 WIPHY_VENDOR_CMD_NEED_NETDEV |
8455 WIPHY_VENDOR_CMD_NEED_RUNNING,
8456 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308457 },
8458#ifdef WLAN_FEATURE_DISA
8459 {
8460 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8461 .info.subcmd =
8462 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8464 WIPHY_VENDOR_CMD_NEED_NETDEV |
8465 WIPHY_VENDOR_CMD_NEED_RUNNING,
8466 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8467 },
8468#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008469};
8470
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008471/**
8472 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8473 * @priv_size: Size of the hdd context.
8474 *
8475 * Allocate wiphy context and hdd context.
8476 *
8477 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008478 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008479hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008480{
8481 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008482 hdd_context_t *hdd_ctx;
8483
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008484 ENTER();
8485
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008486 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8487
8488 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008489 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008490 return NULL;
8491 }
8492
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008493 hdd_ctx = wiphy_priv(wiphy);
8494
8495 hdd_ctx->wiphy = wiphy;
8496
8497 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008498}
8499
8500/*
8501 * FUNCTION: wlan_hdd_cfg80211_update_band
8502 * This function is called from the supplicant through a
8503 * private ioctl to change the band value
8504 */
8505int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8506{
8507 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008508 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008509
8510 ENTER();
8511
8512 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8513
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008514 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008515 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008516
8517 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8518 struct ieee80211_supported_band *band = wiphy->bands[i];
8519
8520 channelEnabledState =
8521 cds_get_channel_state(band->channels[j].
8522 hw_value);
8523
8524 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8525 /* 5G only */
8526#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8527 /* Enable Social channels for P2P */
8528 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8529 (band->channels[j].center_freq)
8530 && CHANNEL_STATE_ENABLE ==
8531 channelEnabledState)
8532 band->channels[j].flags &=
8533 ~IEEE80211_CHAN_DISABLED;
8534 else
8535#endif
8536 band->channels[j].flags |=
8537 IEEE80211_CHAN_DISABLED;
8538 continue;
8539 } else if (IEEE80211_BAND_5GHZ == i &&
8540 eCSR_BAND_24 == eBand) {
8541 /* 2G only */
8542 band->channels[j].flags |=
8543 IEEE80211_CHAN_DISABLED;
8544 continue;
8545 }
8546
Amar Singhal6842e8f2016-02-23 16:30:32 -08008547 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008548 band->channels[j].flags &=
8549 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008550 }
8551 }
8552 return 0;
8553}
8554
8555/*
8556 * FUNCTION: wlan_hdd_cfg80211_init
8557 * This function is called by hdd_wlan_startup()
8558 * during initialization.
8559 * This function is used to initialize and register wiphy structure.
8560 */
8561int wlan_hdd_cfg80211_init(struct device *dev,
8562 struct wiphy *wiphy, struct hdd_config *pCfg)
8563{
8564 int i, j;
8565 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8566
8567 ENTER();
8568
8569 /* Now bind the underlying wlan device with wiphy */
8570 set_wiphy_dev(wiphy, dev);
8571
8572 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008574#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8575 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008576 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008577#else
8578 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008579 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008580#endif
8581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008582 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8583 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8584 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8585#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8586 | WIPHY_FLAG_4ADDR_STATION
8587#endif
8588 | WIPHY_FLAG_OFFCHAN_TX;
8589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008590#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8591 wiphy->wowlan = &wowlan_support_cfg80211_init;
8592#else
8593 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8594 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8595 wiphy->wowlan.pattern_min_len = 1;
8596 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8597#endif
8598
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008599 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008600#ifdef FEATURE_WLAN_ESE
8601 || pCfg->isEseIniFeatureEnabled
8602#endif
8603 ) {
8604 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8605 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008606#ifdef FEATURE_WLAN_TDLS
8607 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8608 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8609#endif
8610
8611 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8612
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008613#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8614 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8615#endif
8616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008617#ifdef FEATURE_WLAN_SCAN_PNO
8618 if (pCfg->configPNOScanSupport) {
8619 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8620 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8621 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8622 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8624 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8625#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008626 }
8627#endif /*FEATURE_WLAN_SCAN_PNO */
8628
8629#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308630 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008631#endif
8632
8633 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8634 driver can still register regulatory callback and
8635 it will get regulatory settings in wiphy->band[], but
8636 driver need to determine what to do with both
8637 regulatory settings */
8638
8639 wiphy->reg_notifier = hdd_reg_notifier;
8640
8641#if defined QCA_WIFI_FTM
8642}
8643#endif
8644
8645 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8646
8647 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8648
8649 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8650
Arun Khandavallifae92942016-08-01 13:31:08 +05308651 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8652 | BIT(NL80211_IFTYPE_ADHOC)
8653 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8654 | BIT(NL80211_IFTYPE_P2P_GO)
8655 | BIT(NL80211_IFTYPE_AP)
8656 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008657
Arun Khandavallifae92942016-08-01 13:31:08 +05308658 if (pCfg->advertiseConcurrentOperation) {
8659 if (pCfg->enableMCC) {
8660 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008661
Arun Khandavallifae92942016-08-01 13:31:08 +05308662 for (i = 0;
8663 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8664 i++) {
8665 if (!pCfg->allowMCCGODiffBI)
8666 wlan_hdd_iface_combination[i].
8667 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008668 }
8669 }
8670 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308671 ARRAY_SIZE(wlan_hdd_iface_combination);
8672 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008673 }
8674
8675 /* Before registering we need to update the ht capabilitied based
8676 * on ini values*/
8677 if (!pCfg->ShortGI20MhzEnable) {
8678 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8679 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008680 }
8681
8682 if (!pCfg->ShortGI40MhzEnable) {
8683 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8684 }
8685
8686 if (!pCfg->nChannelBondingMode5GHz) {
8687 wlan_hdd_band_5_ghz.ht_cap.cap &=
8688 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8689 }
8690
Abhishek Singhf512bf32016-05-04 16:47:46 +05308691 /*
8692 * In case of static linked driver at the time of driver unload,
8693 * module exit doesn't happens. Module cleanup helps in cleaning
8694 * of static memory.
8695 * If driver load happens statically, at the time of driver unload,
8696 * wiphy flags don't get reset because of static memory.
8697 * It's better not to store channel in static memory.
8698 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008699 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308700 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8701 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8702 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8703 hdd_err("Not enough memory to allocate channels");
8704 return -ENOMEM;
8705 }
8706 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8707 &hdd_channels_2_4_ghz[0],
8708 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308709 if ((hdd_is_5g_supported(pHddCtx)) &&
8710 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8711 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8712 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8713 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308715 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8716 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8717 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8718 hdd_err("Not enough memory to allocate channels");
8719 qdf_mem_free(wiphy->
8720 bands[IEEE80211_BAND_2GHZ]->channels);
8721 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8722 return -ENOMEM;
8723 }
8724 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8725 &hdd_channels_5_ghz[0],
8726 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008727 }
8728
8729 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8730
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008731 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008732 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008733
8734 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8735 struct ieee80211_supported_band *band = wiphy->bands[i];
8736
8737 if (IEEE80211_BAND_2GHZ == i &&
8738 eCSR_BAND_5G == pCfg->nBandCapability) {
8739 /* 5G only */
8740#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8741 /* Enable social channels for P2P */
8742 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8743 (band->channels[j].center_freq))
8744 band->channels[j].flags &=
8745 ~IEEE80211_CHAN_DISABLED;
8746 else
8747#endif
8748 band->channels[j].flags |=
8749 IEEE80211_CHAN_DISABLED;
8750 continue;
8751 } else if (IEEE80211_BAND_5GHZ == i &&
8752 eCSR_BAND_24 == pCfg->nBandCapability) {
8753 /* 2G only */
8754 band->channels[j].flags |=
8755 IEEE80211_CHAN_DISABLED;
8756 continue;
8757 }
8758 }
8759 }
8760 /*Initialise the supported cipher suite details */
8761 wiphy->cipher_suites = hdd_cipher_suites;
8762 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8763
8764 /*signal strength in mBm (100*dBm) */
8765 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8766 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8767
Anurag Chouhan6d760662016-02-20 16:05:43 +05308768 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008769 wiphy->n_vendor_commands =
8770 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8771 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8772
8773 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8774 wiphy->n_vendor_events =
8775 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8776 }
8777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008778 if (pCfg->enableDFSMasterCap) {
8779 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8780 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008781
8782 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8783
8784#ifdef QCA_HT_2040_COEX
8785 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8786#endif
8787
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308788 hdd_add_channel_switch_support(&wiphy->flags);
8789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008790 EXIT();
8791 return 0;
8792}
8793
Abhishek Singhf512bf32016-05-04 16:47:46 +05308794/**
8795 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8796 * @ wiphy: the wiphy to validate against
8797 *
8798 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308799 * memory allocated in wlan_hdd_cfg80211_init also
8800 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308801 *
8802 * Return: void
8803 */
8804void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8805{
8806 int i;
8807
8808 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8809 if (NULL != wiphy->bands[i] &&
8810 (NULL != wiphy->bands[i]->channels)) {
8811 qdf_mem_free(wiphy->bands[i]->channels);
8812 wiphy->bands[i]->channels = NULL;
8813 }
8814 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308815 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308816}
8817
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008818/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308819 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008820 * initialization. In wlan_hdd_cfg80211_init, only the
8821 * default values will be initialized. The final initialization
8822 * of all required members can be done here.
8823 */
8824void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8825{
8826 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8827}
8828
8829/* In this function we are registering wiphy. */
8830int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8831{
8832 ENTER();
8833 /* Register our wiphy dev with cfg80211 */
8834 if (0 > wiphy_register(wiphy)) {
8835 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008836 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008837 return -EIO;
8838 }
8839
8840 EXIT();
8841 return 0;
8842}
8843
8844/*
8845 HDD function to update wiphy capability based on target offload status.
8846
8847 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8848 capability even before downloading firmware to the target. In discrete
8849 case, host will get know certain offload capability (say sched_scan
8850 caps) only after downloading firmware to the target and target boots up.
8851 This function is used to override setting done in wlan_hdd_cfg80211_init()
8852 based on target capability.
8853 */
8854void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8855{
8856#ifdef FEATURE_WLAN_SCAN_PNO
8857 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8858 struct hdd_config *pCfg = pHddCtx->config;
8859
8860 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8861 * control comes here. Here just we need to clear it if firmware doesn't
8862 * have PNO support. */
8863 if (!pCfg->PnoOffload) {
8864 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8865 wiphy->max_sched_scan_ssids = 0;
8866 wiphy->max_match_sets = 0;
8867 wiphy->max_sched_scan_ie_len = 0;
8868 }
8869#endif
8870}
8871
8872/* This function registers for all frame which supplicant is interested in */
8873void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8874{
8875 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8876 /* Register for all P2P action, public action etc frames */
8877 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8878
8879 ENTER();
8880
Abhishek Singh7996eb72015-12-30 17:24:02 +05308881 /* Register frame indication call back */
8882 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8883
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308884 /* Register for p2p ack indication */
8885 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008887 /* Right now we are registering these frame when driver is getting
8888 initialized. Once we will move to 2.6.37 kernel, in which we have
8889 frame register ops, we will move this code as a part of that */
8890 /* GAS Initial Request */
8891 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8892 (uint8_t *) GAS_INITIAL_REQ,
8893 GAS_INITIAL_REQ_SIZE);
8894
8895 /* GAS Initial Response */
8896 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8897 (uint8_t *) GAS_INITIAL_RSP,
8898 GAS_INITIAL_RSP_SIZE);
8899
8900 /* GAS Comeback Request */
8901 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8902 (uint8_t *) GAS_COMEBACK_REQ,
8903 GAS_COMEBACK_REQ_SIZE);
8904
8905 /* GAS Comeback Response */
8906 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8907 (uint8_t *) GAS_COMEBACK_RSP,
8908 GAS_COMEBACK_RSP_SIZE);
8909
8910 /* P2P Public Action */
8911 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8912 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8913 P2P_PUBLIC_ACTION_FRAME_SIZE);
8914
8915 /* P2P Action */
8916 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8917 (uint8_t *) P2P_ACTION_FRAME,
8918 P2P_ACTION_FRAME_SIZE);
8919
8920 /* WNM BSS Transition Request frame */
8921 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8922 (uint8_t *) WNM_BSS_ACTION_FRAME,
8923 WNM_BSS_ACTION_FRAME_SIZE);
8924
8925 /* WNM-Notification */
8926 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8927 (uint8_t *) WNM_NOTIFICATION_FRAME,
8928 WNM_NOTIFICATION_FRAME_SIZE);
8929}
8930
8931void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
8932{
8933 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8934 /* Register for all P2P action, public action etc frames */
8935 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8936
8937 ENTER();
8938
8939 /* Right now we are registering these frame when driver is getting
8940 initialized. Once we will move to 2.6.37 kernel, in which we have
8941 frame register ops, we will move this code as a part of that */
8942 /* GAS Initial Request */
8943
8944 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8945 (uint8_t *) GAS_INITIAL_REQ,
8946 GAS_INITIAL_REQ_SIZE);
8947
8948 /* GAS Initial Response */
8949 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8950 (uint8_t *) GAS_INITIAL_RSP,
8951 GAS_INITIAL_RSP_SIZE);
8952
8953 /* GAS Comeback Request */
8954 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8955 (uint8_t *) GAS_COMEBACK_REQ,
8956 GAS_COMEBACK_REQ_SIZE);
8957
8958 /* GAS Comeback Response */
8959 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8960 (uint8_t *) GAS_COMEBACK_RSP,
8961 GAS_COMEBACK_RSP_SIZE);
8962
8963 /* P2P Public Action */
8964 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8965 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8966 P2P_PUBLIC_ACTION_FRAME_SIZE);
8967
8968 /* P2P Action */
8969 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8970 (uint8_t *) P2P_ACTION_FRAME,
8971 P2P_ACTION_FRAME_SIZE);
8972
8973 /* WNM-Notification */
8974 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
8975 (uint8_t *) WNM_NOTIFICATION_FRAME,
8976 WNM_NOTIFICATION_FRAME_SIZE);
8977}
8978
8979#ifdef FEATURE_WLAN_WAPI
8980void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
8981 const uint8_t *mac_addr, const uint8_t *key,
8982 int key_Len)
8983{
8984 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8985 tCsrRoamSetKey setKey;
8986 bool isConnected = true;
8987 int status = 0;
8988 uint32_t roamId = 0xFF;
8989 uint8_t *pKeyPtr = NULL;
8990 int n = 0;
8991
Jeff Johnson46b40792016-06-29 14:03:14 -07008992 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008993 hdd_device_mode_to_string(pAdapter->device_mode),
8994 pAdapter->device_mode);
8995
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308996 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008997 setKey.keyId = key_index; /* Store Key ID */
8998 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
8999 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9000 setKey.paeRole = 0; /* the PAE role */
9001 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309002 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009003 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309004 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009005 }
9006 setKey.keyLength = key_Len;
9007 pKeyPtr = setKey.Key;
9008 memcpy(pKeyPtr, key, key_Len);
9009
Jeff Johnson46b40792016-06-29 14:03:14 -07009010 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009011 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009012 hdd_notice("WAPI KEY Data[%d]:%02x ",
9013 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009014
9015 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9016 if (isConnected) {
9017 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9018 pAdapter->sessionId, &setKey, &roamId);
9019 }
9020 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009021 hdd_err("sme_roam_set_key returned ERROR status= %d",
9022 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9024 }
9025}
9026#endif /* FEATURE_WLAN_WAPI */
9027
9028uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9029 uint8_t eid)
9030{
9031 int left = length;
9032 uint8_t *ptr = (uint8_t *)ies_ptr;
9033 uint8_t elem_id, elem_len;
9034
9035 while (left >= 2) {
9036 elem_id = ptr[0];
9037 elem_len = ptr[1];
9038 left -= 2;
9039 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009040 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009041 eid, elem_len, left);
9042 return NULL;
9043 }
9044 if (elem_id == eid) {
9045 return ptr;
9046 }
9047
9048 left -= elem_len;
9049 ptr += (elem_len + 2);
9050 }
9051 return NULL;
9052}
9053
9054/*
9055 * FUNCTION: wlan_hdd_validate_operation_channel
9056 * called by wlan_hdd_cfg80211_start_bss() and
9057 * wlan_hdd_set_channel()
9058 * This function validates whether given channel is part of valid
9059 * channel list.
9060 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309061QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009062 int channel)
9063{
9064
9065 uint32_t num_ch = 0;
9066 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9067 u32 indx = 0;
9068 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9069 uint8_t fValidChannel = false, count = 0;
9070 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9071
9072 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9073
9074 if (hdd_pConfig_ini->sapAllowAllChannel) {
9075 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009076 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009077 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009078 fValidChannel = true;
9079 break;
9080 }
9081 }
9082 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009083 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309084 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009085 }
9086 } else {
9087 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9088 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009089 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309090 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009091 }
9092 for (indx = 0; indx < num_ch; indx++) {
9093 if (channel == valid_ch[indx]) {
9094 break;
9095 }
9096 }
9097
9098 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009099 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309100 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009101 }
9102 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309103 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009104
9105}
9106
9107#ifdef DHCP_SERVER_OFFLOAD
9108static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9109{
9110 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9111 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9112 uint8_t numEntries = 0;
9113 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9114 uint8_t num;
9115 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309116 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009118 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009119 return;
9120 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309121 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009122 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9123 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9124 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9125 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9126 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9127 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009128 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009129 goto end;
9130 }
9131 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009132 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009133 goto end;
9134 }
9135 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009136 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137 goto end;
9138 }
9139 for (num = 0; num < numEntries; num++) {
9140 temp = srv_ip[num];
9141 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9142 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309143 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009144 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009145 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009146 goto end;
9147 }
Jeff Johnson77848112016-06-29 14:52:06 -07009148 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009149end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309150 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009151 return;
9152}
9153#endif /* DHCP_SERVER_OFFLOAD */
9154
9155static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9156 struct net_device *dev,
9157 struct bss_parameters *params)
9158{
9159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9160 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9161 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309162 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009163
9164 ENTER();
9165
Anurag Chouhan6d760662016-02-20 16:05:43 +05309166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009167 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009168 return -EINVAL;
9169 }
9170
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309171 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9173 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009174 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009175 hdd_device_mode_to_string(pAdapter->device_mode),
9176 pAdapter->device_mode, params->ap_isolate);
9177
9178 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9179 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309180 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009181 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009182
Krunal Sonib4326f22016-03-10 13:05:51 -08009183 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9184 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009185 return -EOPNOTSUPP;
9186 }
9187
9188 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9189 * want to update this parameter */
9190 if (-1 != params->ap_isolate) {
9191 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9192 !!params->ap_isolate;
9193
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309194 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009195 pAdapter->sessionId,
9196 pAdapter->sessionCtx.
9197 ap.
9198 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309199 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009200 ret = -EINVAL;
9201 }
9202 }
9203
9204 EXIT();
9205 return ret;
9206}
9207
Krunal Soni8c37e322016-02-03 16:08:37 -08009208/**
9209 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9210 * @ndev: pointer to net device provided by supplicant
9211 * @type: type of the interface, upper layer wanted to change
9212 *
9213 * Upper layer provides the new interface mode that needs to be changed
9214 * for given net device
9215 *
9216 * Return: success or failure in terms of integer value
9217 */
9218static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009219 enum nl80211_iftype type)
9220{
Krunal Soni8c37e322016-02-03 16:08:37 -08009221 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9222 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9223 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009224 hdd_wext_state_t *wext;
9225 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309226 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009227
9228 ENTER();
9229
Krunal Soni8c37e322016-02-03 16:08:37 -08009230 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009231 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009232 return 0;
9233 }
9234
9235 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009236 hdd_stop_adapter(hdd_ctx, adapter, true);
9237 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009238 wdev->iftype = type;
9239 /*Check for sub-string p2p to confirm its a p2p interface */
9240 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009241 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009242 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009243 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009244 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009245 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009246 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009247 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009248 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009249 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009250 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009251 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9252 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009253 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9254 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009255 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009256 adapter->scan_info.scanAddIE.length;
9257 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309258 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009259 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9260 wext->roamProfile.phyMode =
9261 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9262 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009263 EXIT();
9264 return status;
9265}
9266
9267static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9268 struct net_device *dev,
9269 struct bss_parameters *params)
9270{
9271 int ret;
9272
9273 cds_ssr_protect(__func__);
9274 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9275 cds_ssr_unprotect(__func__);
9276
9277 return ret;
9278}
9279
9280/* FUNCTION: wlan_hdd_change_country_code_cd
9281 * to wait for contry code completion
9282 */
9283void *wlan_hdd_change_country_code_cb(void *pAdapter)
9284{
9285 hdd_adapter_t *call_back_pAdapter = pAdapter;
9286 complete(&call_back_pAdapter->change_country_code);
9287 return NULL;
9288}
9289
Rajeev Kumar98edb772016-01-19 12:42:19 -08009290/**
9291 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9292 * @wiphy: Pointer to the wiphy structure
9293 * @ndev: Pointer to the net device
9294 * @type: Interface type
9295 * @flags: Flags for change interface
9296 * @params: Pointer to change interface parameters
9297 *
9298 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 */
9300static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9301 struct net_device *ndev,
9302 enum nl80211_iftype type,
9303 u32 *flags,
9304 struct vif_params *params)
9305{
9306 struct wireless_dev *wdev;
9307 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9308 hdd_context_t *pHddCtx;
9309 tCsrRoamProfile *pRoamProfile = NULL;
9310 eCsrRoamBssType LastBSSType;
9311 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309312 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009313 int status;
9314
9315 ENTER();
9316
Anurag Chouhan6d760662016-02-20 16:05:43 +05309317 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009318 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009319 return -EINVAL;
9320 }
9321
9322 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9323 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309324 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009325 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009326
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309327 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009328 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9329 pAdapter->sessionId, type));
9330
Jeff Johnson77848112016-06-29 14:52:06 -07009331 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009332 pAdapter->device_mode, type);
9333
Arun Khandavallifae92942016-08-01 13:31:08 +05309334 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9335 if (status) {
9336 hdd_err("Failed to start modules");
9337 return -EINVAL;
9338 }
9339
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009340 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009341 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9342 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009343 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009344 return -EINVAL;
9345 }
9346
9347 pConfig = pHddCtx->config;
9348 wdev = ndev->ieee80211_ptr;
9349
9350 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009351 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009352
9353 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9354
Krunal Sonib4326f22016-03-10 13:05:51 -08009355 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9356 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9357 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9358 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009359 hdd_wext_state_t *pWextState =
9360 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9361
9362 pRoamProfile = &pWextState->roamProfile;
9363 LastBSSType = pRoamProfile->BSSType;
9364
9365 switch (type) {
9366 case NL80211_IFTYPE_STATION:
9367 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009368 case NL80211_IFTYPE_ADHOC:
9369 if (type == NL80211_IFTYPE_ADHOC) {
9370 wlan_hdd_tdls_exit(pAdapter);
9371 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009372 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009373 }
9374 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9375 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309376 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309378 if (hdd_start_adapter(pAdapter)) {
9379 hdd_err("Failed to start adapter :%d",
9380 pAdapter->device_mode);
9381 return -EINVAL;
9382 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009383 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009384 case NL80211_IFTYPE_AP:
9385 case NL80211_IFTYPE_P2P_GO:
9386 {
Jeff Johnson77848112016-06-29 14:52:06 -07009387 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009388 (type ==
9389 NL80211_IFTYPE_AP) ? "SoftAP" :
9390 "P2pGo");
9391
9392 /* Cancel any remain on channel for GO mode */
9393 if (NL80211_IFTYPE_P2P_GO == type) {
9394 wlan_hdd_cancel_existing_remain_on_channel
9395 (pAdapter);
9396 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009397
Arun Khandavallifae92942016-08-01 13:31:08 +05309398 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009399 /* De-init the adapter */
9400 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9401 memset(&pAdapter->sessionCtx, 0,
9402 sizeof(pAdapter->sessionCtx));
9403 pAdapter->device_mode =
9404 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009405 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9406 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009407
9408 /*
9409 * Fw will take care incase of concurrency
9410 */
9411
Krunal Sonib4326f22016-03-10 13:05:51 -08009412 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009413 && (pConfig->apRandomBssidEnabled)) {
9414 /* To meet Android requirements create a randomized
9415 MAC address of the form 02:1A:11:Fx:xx:xx */
9416 get_random_bytes(&ndev->dev_addr[3], 3);
9417 ndev->dev_addr[0] = 0x02;
9418 ndev->dev_addr[1] = 0x1A;
9419 ndev->dev_addr[2] = 0x11;
9420 ndev->dev_addr[3] |= 0xF0;
9421 memcpy(pAdapter->macAddressCurrent.
9422 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309423 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 pr_info("wlan: Generated HotSpot BSSID "
9425 MAC_ADDRESS_STR "\n",
9426 MAC_ADDR_ARRAY(ndev->dev_addr));
9427 }
9428
9429 hdd_set_ap_ops(pAdapter->dev);
9430
Arun Khandavallifae92942016-08-01 13:31:08 +05309431 if (hdd_start_adapter(pAdapter)) {
9432 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009433 return -EINVAL;
9434 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 /* Interface type changed update in wiphy structure */
9436 if (wdev) {
9437 wdev->iftype = type;
9438 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009439 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009440 return -EINVAL;
9441 }
9442 goto done;
9443 }
9444
9445 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009446 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009447 type);
9448 return -EOPNOTSUPP;
9449 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009450 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9451 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009452 switch (type) {
9453 case NL80211_IFTYPE_STATION:
9454 case NL80211_IFTYPE_P2P_CLIENT:
9455 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009456 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9457 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309458 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009459 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309460 if (hdd_start_adapter(pAdapter)) {
9461 hdd_err("Failed to start adapter :%d",
9462 pAdapter->device_mode);
9463 return -EINVAL;
9464 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009465 goto done;
9466
9467 case NL80211_IFTYPE_AP:
9468 case NL80211_IFTYPE_P2P_GO:
9469 wdev->iftype = type;
9470 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009471 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009472 goto done;
9473
9474 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009475 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009476 type);
9477 return -EOPNOTSUPP;
9478 }
9479 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009480 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009481 pAdapter->device_mode);
9482 return -EOPNOTSUPP;
9483 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009484done:
9485 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009486 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009487
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009488 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489
9490 EXIT();
9491 return 0;
9492}
9493
Rajeev Kumar98edb772016-01-19 12:42:19 -08009494/**
9495 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9496 * @wiphy: Pointer to the wiphy structure
9497 * @ndev: Pointer to the net device
9498 * @type: Interface type
9499 * @flags: Flags for change interface
9500 * @params: Pointer to change interface parameters
9501 *
9502 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009503 */
9504static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9505 struct net_device *ndev,
9506 enum nl80211_iftype type,
9507 u32 *flags,
9508 struct vif_params *params)
9509{
9510 int ret;
9511
9512 cds_ssr_protect(__func__);
9513 ret =
9514 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9515 cds_ssr_unprotect(__func__);
9516
9517 return ret;
9518}
9519
9520#ifdef FEATURE_WLAN_TDLS
9521static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9522 int index, uint8_t match)
9523{
9524 int i;
9525 for (i = 0; i < index; i++) {
9526 if (arr[i] == match)
9527 return true;
9528 }
9529 return false;
9530}
9531#endif
9532
9533/**
9534 * __wlan_hdd_change_station() - change station
9535 * @wiphy: Pointer to the wiphy structure
9536 * @dev: Pointer to the net device.
9537 * @mac: bssid
9538 * @params: Pointer to station parameters
9539 *
9540 * Return: 0 for success, error number on failure.
9541 */
9542#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9543static int __wlan_hdd_change_station(struct wiphy *wiphy,
9544 struct net_device *dev,
9545 const uint8_t *mac,
9546 struct station_parameters *params)
9547#else
9548static int __wlan_hdd_change_station(struct wiphy *wiphy,
9549 struct net_device *dev,
9550 uint8_t *mac,
9551 struct station_parameters *params)
9552#endif
9553{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309554 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9556 hdd_context_t *pHddCtx;
9557 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309558 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009559#ifdef FEATURE_WLAN_TDLS
9560 tCsrStaParams StaParams = { 0 };
9561 uint8_t isBufSta = 0;
9562 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309563 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009564#endif
9565 int ret;
9566
9567 ENTER();
9568
Anurag Chouhan6d760662016-02-20 16:05:43 +05309569 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009570 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009571 return -EINVAL;
9572 }
9573
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309574 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009575 TRACE_CODE_HDD_CHANGE_STATION,
9576 pAdapter->sessionId, params->listen_interval));
9577
9578 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9579 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309580 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009582
9583 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9584
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309585 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586
Krunal Sonib4326f22016-03-10 13:05:51 -08009587 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9588 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009589 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9590 status =
9591 hdd_softap_change_sta_state(pAdapter,
9592 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009593 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309595 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009596 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009597 return -EINVAL;
9598 }
9599 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009600 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9601 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009602#ifdef FEATURE_WLAN_TDLS
9603 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009604
9605 if (cds_is_sub_20_mhz_enabled()) {
9606 hdd_err("TDLS not allowed with sub 20 MHz");
9607 return -EINVAL;
9608 }
9609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 StaParams.capability = params->capability;
9611 StaParams.uapsd_queues = params->uapsd_queues;
9612 StaParams.max_sp = params->max_sp;
9613
9614 /* Convert (first channel , number of channels) tuple to
9615 * the total list of channels. This goes with the assumption
9616 * that if the first channel is < 14, then the next channels
9617 * are an incremental of 1 else an incremental of 4 till the number
9618 * of channels.
9619 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009620 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009621 if (0 != params->supported_channels_len) {
9622 int i = 0, j = 0, k = 0, no_of_channels = 0;
9623 int num_unique_channels;
9624 int next;
9625 for (i = 0;
9626 i < params->supported_channels_len
9627 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9628 int wifi_chan_index;
9629 if (!wlan_hdd_is_duplicate_channel
9630 (StaParams.supported_channels, j,
9631 params->supported_channels[i])) {
9632 StaParams.
9633 supported_channels[j] =
9634 params->
9635 supported_channels[i];
9636 } else {
9637 continue;
9638 }
9639 wifi_chan_index =
9640 ((StaParams.supported_channels[j] <=
9641 HDD_CHANNEL_14) ? 1 : 4);
9642 no_of_channels =
9643 params->supported_channels[i + 1];
9644
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009645 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 -08009646 StaParams.
9647 supported_channels[j],
9648 wifi_chan_index,
9649 no_of_channels);
9650 for (k = 1; k <= no_of_channels &&
9651 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9652 k++) {
9653 next =
9654 StaParams.
9655 supported_channels[j] +
9656 wifi_chan_index;
9657 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9658 StaParams.
9659 supported_channels[j
9660 +
9661 1]
9662 = next;
9663 } else {
9664 continue;
9665 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009666 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 j + 1,
9668 StaParams.
9669 supported_channels[j +
9670 1]);
9671 j += 1;
9672 }
9673 }
9674 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009675 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009676 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009677 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678 StaParams.
9679 supported_channels[i]);
9680 }
9681 if (MAX_CHANNEL < num_unique_channels)
9682 num_unique_channels = MAX_CHANNEL;
9683 StaParams.supported_channels_len =
9684 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009685 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686 StaParams.supported_channels_len);
9687 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309688 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009689 params->supported_oper_classes,
9690 params->supported_oper_classes_len);
9691 StaParams.supported_oper_classes_len =
9692 params->supported_oper_classes_len;
9693
9694 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309695 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009696 params->ext_capab,
9697 sizeof(StaParams.extn_capability));
9698
9699 if (NULL != params->ht_capa) {
9700 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309701 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 sizeof(tSirHTCap));
9703 }
9704
9705 StaParams.supported_rates_len =
9706 params->supported_rates_len;
9707
9708 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9709 * The supported_rates array , for all the structures propogating till Add Sta
9710 * to the firmware has to be modified , if the supplicant (ieee80211) is
9711 * modified to send more rates.
9712 */
9713
9714 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9715 */
9716 if (StaParams.supported_rates_len >
9717 SIR_MAC_MAX_SUPP_RATES)
9718 StaParams.supported_rates_len =
9719 SIR_MAC_MAX_SUPP_RATES;
9720
9721 if (0 != StaParams.supported_rates_len) {
9722 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309723 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 params->supported_rates,
9725 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009726 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009727 StaParams.supported_rates_len);
9728 for (i = 0; i < StaParams.supported_rates_len;
9729 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009730 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009731 StaParams.supported_rates[i]);
9732 }
9733
9734 if (NULL != params->vht_capa) {
9735 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309736 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009737 params->vht_capa,
9738 sizeof(tSirVHTCap));
9739 }
9740
9741 if (0 != params->ext_capab_len) {
9742 /*Define A Macro : TODO Sunil */
9743 if ((1 << 4) & StaParams.extn_capability[3]) {
9744 isBufSta = 1;
9745 }
9746 /* TDLS Channel Switching Support */
9747 if ((1 << 6) & StaParams.extn_capability[3]) {
9748 isOffChannelSupported = 1;
9749 }
9750 }
9751
Nitesh Shah99934ac2016-09-05 15:54:08 +05309752 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309753 (params->ht_capa || params->vht_capa ||
9754 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309755 is_qos_wmm_sta = true;
9756
9757 hdd_notice("%s: TDLS Peer is QOS capable"
9758 " is_qos_wmm_sta= %d HTcapPresent = %d",
9759 __func__, is_qos_wmm_sta,
9760 StaParams.htcap_present);
9761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009762 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309763 &StaParams,
9764 isBufSta,
9765 isOffChannelSupported,
9766 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309767 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009768 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769 return -EINVAL;
9770 }
9771
9772 status =
9773 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9774 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309775 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009776 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009777 return -EINVAL;
9778 }
9779 }
9780#endif
9781 }
9782 EXIT();
9783 return ret;
9784}
9785
9786/**
9787 * wlan_hdd_change_station() - cfg80211 change station handler function
9788 * @wiphy: Pointer to the wiphy structure
9789 * @dev: Pointer to the net device.
9790 * @mac: bssid
9791 * @params: Pointer to station parameters
9792 *
9793 * This is the cfg80211 change station handler function which invokes
9794 * the internal function @__wlan_hdd_change_station with
9795 * SSR protection.
9796 *
9797 * Return: 0 for success, error number on failure.
9798 */
9799#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9800static int wlan_hdd_change_station(struct wiphy *wiphy,
9801 struct net_device *dev,
9802 const u8 *mac,
9803 struct station_parameters *params)
9804#else
9805static int wlan_hdd_change_station(struct wiphy *wiphy,
9806 struct net_device *dev,
9807 u8 *mac,
9808 struct station_parameters *params)
9809#endif
9810{
9811 int ret;
9812
9813 cds_ssr_protect(__func__);
9814 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9815 cds_ssr_unprotect(__func__);
9816
9817 return ret;
9818}
9819
9820/*
9821 * FUNCTION: __wlan_hdd_cfg80211_add_key
9822 * This function is used to initialize the key information
9823 */
9824static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9825 struct net_device *ndev,
9826 u8 key_index, bool pairwise,
9827 const u8 *mac_addr,
9828 struct key_params *params)
9829{
9830 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9831 tCsrRoamSetKey setKey;
9832 int status;
9833 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309835 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009836 hdd_context_t *pHddCtx;
9837 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9838
9839 ENTER();
9840
Anurag Chouhan6d760662016-02-20 16:05:43 +05309841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009842 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009843 return -EINVAL;
9844 }
9845
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309846 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009847 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9848 pAdapter->sessionId, params->key_len));
9849 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9850 status = wlan_hdd_validate_context(pHddCtx);
9851
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309852 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009853 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009855 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009856 hdd_device_mode_to_string(pAdapter->device_mode),
9857 pAdapter->device_mode);
9858
9859 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009860 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009861
9862 return -EINVAL;
9863 }
9864
9865 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009866 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009867
9868 return -EINVAL;
9869 }
9870
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009871 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009872
9873 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309874 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875 setKey.keyId = key_index;
9876 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309877 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009878
9879 switch (params->cipher) {
9880 case WLAN_CIPHER_SUITE_WEP40:
9881 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9882 break;
9883
9884 case WLAN_CIPHER_SUITE_WEP104:
9885 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9886 break;
9887
9888 case WLAN_CIPHER_SUITE_TKIP:
9889 {
9890 u8 *pKey = &setKey.Key[0];
9891 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9892
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309893 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009894
9895 /*Supplicant sends the 32bytes key in this order
9896
9897 |--------------|----------|----------|
9898 | Tk1 |TX-MIC | RX Mic |
9899 |||--------------|----------|----------|
9900 <---16bytes---><--8bytes--><--8bytes-->
9901
9902 */
9903 /*Sme expects the 32 bytes key to be in the below order
9904
9905 |--------------|----------|----------|
9906 | Tk1 |RX-MIC | TX Mic |
9907 |||--------------|----------|----------|
9908 <---16bytes---><--8bytes--><--8bytes-->
9909 */
9910 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309911 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009912
9913 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309914 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009915
9916 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309917 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009918
9919 break;
9920 }
9921
9922 case WLAN_CIPHER_SUITE_CCMP:
9923 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9924 break;
9925
9926#ifdef FEATURE_WLAN_WAPI
9927 case WLAN_CIPHER_SUITE_SMS4:
9928 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309929 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9931 mac_addr, params->key,
9932 params->key_len);
9933 return 0;
9934 }
9935#endif
9936
9937#ifdef FEATURE_WLAN_ESE
9938 case WLAN_CIPHER_SUITE_KRK:
9939 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9940 break;
9941#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9942 case WLAN_CIPHER_SUITE_BTK:
9943 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9944 break;
9945#endif
9946#endif
9947
9948#ifdef WLAN_FEATURE_11W
9949 case WLAN_CIPHER_SUITE_AES_CMAC:
9950 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9951 break;
9952#endif
9953
9954 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009955 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009956 return -EOPNOTSUPP;
9957 }
9958
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009959 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009960
9961 if (!pairwise) {
9962 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009963 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009964 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309965 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009966 } else {
9967 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009968 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009969 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309970 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009971 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009972 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009973 /* if a key is already installed, block all subsequent ones */
9974 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009975 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009976 return 0;
9977 }
9978
9979 setKey.keyDirection = eSIR_TX_RX;
9980 /*Set the group key */
9981 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9982 pAdapter->sessionId, &setKey, &roamId);
9983
9984 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009985 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 return -EINVAL;
9987 }
9988 /*Save the keys here and call sme_roam_set_key for setting
9989 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309990 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009991 &setKey, sizeof(tCsrRoamSetKey));
9992
9993 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
9994 return status;
9995 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009996 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9997 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9999 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010000 status = wlansap_set_key_sta(
10001 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010002 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010003 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004 __LINE__, status);
10005 }
10006 }
10007
10008 /* Save the key in ap ctx for use on START_BASS and restart */
10009 if (pairwise ||
10010 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10011 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010012 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010013 sizeof(tCsrRoamSetKey));
10014 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010015 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010016 sizeof(tCsrRoamSetKey));
10017
Krunal Sonib4326f22016-03-10 13:05:51 -080010018 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10019 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010020 hdd_wext_state_t *pWextState =
10021 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10022 hdd_station_ctx_t *pHddStaCtx =
10023 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10024
10025 if (!pairwise) {
10026 /* set group key */
10027 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010028 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010029 __func__, __LINE__);
10030 hdd_perform_roam_set_key_complete(pAdapter);
10031 }
10032 }
10033
10034 pWextState->roamProfile.Keys.KeyLength[key_index] =
10035 (u8) params->key_len;
10036
10037 pWextState->roamProfile.Keys.defaultIndex = key_index;
10038
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010039 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010040 KeyMaterial[key_index][0], params->key,
10041 params->key_len);
10042
10043 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10044
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010045 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10047 setKey.keyDirection);
10048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049 /* The supplicant may attempt to set the PTK once pre-authentication
10050 is done. Save the key in the UMAC and include it in the ADD BSS
10051 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010052 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010053 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010054 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010055 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010057 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010058 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010059 return -EINVAL;
10060 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061
10062 /* issue set key request to SME */
10063 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10064 pAdapter->sessionId, &setKey, &roamId);
10065
10066 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010067 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010068 pHddStaCtx->roam_info.roamingState =
10069 HDD_ROAM_STATE_NONE;
10070 return -EINVAL;
10071 }
10072
10073 /* in case of IBSS as there was no information available about WEP keys during
10074 * IBSS join, group key intialized with NULL key, so re-initialize group key
10075 * with correct value*/
10076 if ((eCSR_BSS_TYPE_START_IBSS ==
10077 pWextState->roamProfile.BSSType)
10078 &&
10079 !((IW_AUTH_KEY_MGMT_802_1X ==
10080 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10081 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10082 pHddStaCtx->conn_info.authType)
10083 )
10084 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10085 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10086 )
10087 ) {
10088 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010089 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010090
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010091 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10093 setKey.keyDirection);
10094
10095 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10096 pAdapter->sessionId, &setKey,
10097 &roamId);
10098
10099 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010100 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101 pHddStaCtx->roam_info.roamingState =
10102 HDD_ROAM_STATE_NONE;
10103 return -EINVAL;
10104 }
10105 }
10106 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010107 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010108 return 0;
10109}
10110
10111static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10112 struct net_device *ndev,
10113 u8 key_index, bool pairwise,
10114 const u8 *mac_addr,
10115 struct key_params *params)
10116{
10117 int ret;
10118 cds_ssr_protect(__func__);
10119 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10120 mac_addr, params);
10121 cds_ssr_unprotect(__func__);
10122
10123 return ret;
10124}
10125
10126/*
10127 * FUNCTION: __wlan_hdd_cfg80211_get_key
10128 * This function is used to get the key information
10129 */
10130static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10131 struct net_device *ndev,
10132 u8 key_index, bool pairwise,
10133 const u8 *mac_addr, void *cookie,
10134 void (*callback)(void *cookie,
10135 struct key_params *)
10136 )
10137{
10138 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10139 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10140 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10141 struct key_params params;
10142
10143 ENTER();
10144
Anurag Chouhan6d760662016-02-20 16:05:43 +053010145 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010146 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147 return -EINVAL;
10148 }
10149
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010150 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151 hdd_device_mode_to_string(pAdapter->device_mode),
10152 pAdapter->device_mode);
10153
10154 memset(&params, 0, sizeof(params));
10155
10156 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010157 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158 key_index);
10159 return -EINVAL;
10160 }
10161
10162 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10163 case eCSR_ENCRYPT_TYPE_NONE:
10164 params.cipher = IW_AUTH_CIPHER_NONE;
10165 break;
10166
10167 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10168 case eCSR_ENCRYPT_TYPE_WEP40:
10169 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10170 break;
10171
10172 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10173 case eCSR_ENCRYPT_TYPE_WEP104:
10174 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10175 break;
10176
10177 case eCSR_ENCRYPT_TYPE_TKIP:
10178 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10179 break;
10180
10181 case eCSR_ENCRYPT_TYPE_AES:
10182 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10183 break;
10184
10185 default:
10186 params.cipher = IW_AUTH_CIPHER_NONE;
10187 break;
10188 }
10189
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010190 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 TRACE_CODE_HDD_CFG80211_GET_KEY,
10192 pAdapter->sessionId, params.cipher));
10193
10194 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10195 params.seq_len = 0;
10196 params.seq = NULL;
10197 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10198 callback(cookie, &params);
10199
10200 EXIT();
10201 return 0;
10202}
10203
10204static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10205 struct net_device *ndev,
10206 u8 key_index, bool pairwise,
10207 const u8 *mac_addr, void *cookie,
10208 void (*callback)(void *cookie,
10209 struct key_params *)
10210 )
10211{
10212 int ret;
10213
10214 cds_ssr_protect(__func__);
10215 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10216 mac_addr, cookie, callback);
10217 cds_ssr_unprotect(__func__);
10218
10219 return ret;
10220}
10221
10222/**
10223 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10224 * @wiphy: wiphy interface context
10225 * @ndev: pointer to net device
10226 * @key_index: Key index used in 802.11 frames
10227 * @unicast: true if it is unicast key
10228 * @multicast: true if it is multicast key
10229 *
10230 * This function is required for cfg80211_ops API.
10231 * It is used to delete the key information
10232 * Underlying hardware implementation does not have API to delete the
10233 * encryption key. It is automatically deleted when the peer is
10234 * removed. Hence this function currently does nothing.
10235 * Future implementation may interprete delete key operation to
10236 * replacing the key with a random junk value, effectively making it
10237 * useless.
10238 *
10239 * Return: status code, always 0.
10240 */
10241
10242static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10243 struct net_device *ndev,
10244 u8 key_index,
10245 bool pairwise, const u8 *mac_addr)
10246{
10247 EXIT();
10248 return 0;
10249}
10250
10251/**
10252 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10253 * @wiphy: Pointer to wiphy structure.
10254 * @dev: Pointer to net_device structure.
10255 * @key_index: key index
10256 * @pairwise: pairwise
10257 * @mac_addr: mac address
10258 *
10259 * This is the cfg80211 delete key handler function which invokes
10260 * the internal function @__wlan_hdd_cfg80211_del_key with
10261 * SSR protection.
10262 *
10263 * Return: 0 for success, error number on failure.
10264 */
10265static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10266 struct net_device *dev,
10267 u8 key_index,
10268 bool pairwise, const u8 *mac_addr)
10269{
10270 int ret;
10271
10272 cds_ssr_protect(__func__);
10273 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10274 pairwise, mac_addr);
10275 cds_ssr_unprotect(__func__);
10276
10277 return ret;
10278}
10279
10280/*
10281 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10282 * This function is used to set the default tx key index
10283 */
10284static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10285 struct net_device *ndev,
10286 u8 key_index,
10287 bool unicast, bool multicast)
10288{
10289 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10290 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10291 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10292 hdd_context_t *pHddCtx;
10293 int status;
10294
10295 ENTER();
10296
Anurag Chouhan6d760662016-02-20 16:05:43 +053010297 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010298 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010299 return -EINVAL;
10300 }
10301
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010302 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010303 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10304 pAdapter->sessionId, key_index));
10305
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010306 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010307 hdd_device_mode_to_string(pAdapter->device_mode),
10308 pAdapter->device_mode, key_index);
10309
10310 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010311 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 return -EINVAL;
10313 }
10314
10315 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10316 status = wlan_hdd_validate_context(pHddCtx);
10317
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010318 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010319 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010320
Krunal Sonib4326f22016-03-10 13:05:51 -080010321 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10322 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10324 pHddStaCtx->conn_info.ucEncryptionType) &&
10325 (eCSR_ENCRYPT_TYPE_AES !=
10326 pHddStaCtx->conn_info.ucEncryptionType)) {
10327 /* If default key index is not same as previous one,
10328 * then update the default key index */
10329
10330 tCsrRoamSetKey setKey;
10331 uint32_t roamId = 0xFF;
10332 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10333
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010334 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010335
10336 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010337 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010338 setKey.keyId = key_index;
10339 setKey.keyLength = Keys->KeyLength[key_index];
10340
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010341 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010342 &Keys->KeyMaterial[key_index][0],
10343 Keys->KeyLength[key_index]);
10344
10345 setKey.keyDirection = eSIR_TX_RX;
10346
Anurag Chouhanc5548422016-02-24 18:33:27 +053010347 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010348 &pHddStaCtx->conn_info.bssId);
10349
10350 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10351 pWextState->roamProfile.EncryptionType.
10352 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10353 /* In the case of dynamic wep supplicant hardcodes DWEP type
10354 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10355 * WEP-40 encryption. In this canse the key length is 5 but the
10356 * encryption type is 104 hence checking the key langht(5) and
10357 * encryption type(104) and switching encryption type to 40*/
10358 pWextState->roamProfile.EncryptionType.
10359 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10360 pWextState->roamProfile.mcEncryptionType.
10361 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10362 }
10363
10364 setKey.encType =
10365 pWextState->roamProfile.EncryptionType.
10366 encryptionType[0];
10367
10368 /* Issue set key request */
10369 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10370 pAdapter->sessionId, &setKey,
10371 &roamId);
10372
10373 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010374 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010375 status);
10376 return -EINVAL;
10377 }
10378 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010379 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010380 /* In SoftAp mode setting key direction for default mode */
10381 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10382 pWextState->roamProfile.EncryptionType.encryptionType[0])
10383 && (eCSR_ENCRYPT_TYPE_AES !=
10384 pWextState->roamProfile.EncryptionType.
10385 encryptionType[0])) {
10386 /* Saving key direction for default key index to TX default */
10387 hdd_ap_ctx_t *pAPCtx =
10388 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10389 pAPCtx->wepKey[key_index].keyDirection =
10390 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010391 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010392 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010393 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010394 }
10395 }
10396
10397 EXIT();
10398 return status;
10399}
10400
10401static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10402 struct net_device *ndev,
10403 u8 key_index,
10404 bool unicast, bool multicast)
10405{
10406 int ret;
10407 cds_ssr_protect(__func__);
10408 ret =
10409 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10410 multicast);
10411 cds_ssr_unprotect(__func__);
10412
10413 return ret;
10414}
10415
Abhishek Singhc9941602016-08-09 16:06:22 +053010416/*
10417 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10418 * @wiphy: wiphy pointer
10419 * @channel: channel of the BSS
10420 * @bssid: Bssid of BSS
10421 * @ssid: Ssid of the BSS
10422 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010423 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010424 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010425 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010426#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010427static
Abhishek Singhc9941602016-08-09 16:06:22 +053010428struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10429 struct ieee80211_channel *channel, const u8 *bssid,
10430 const u8 *ssid, size_t ssid_len)
10431{
10432 return cfg80211_get_bss(wiphy, channel, bssid,
10433 ssid,
10434 ssid_len,
10435 WLAN_CAPABILITY_ESS,
10436 WLAN_CAPABILITY_ESS);
10437}
10438#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010439static
Abhishek Singhc9941602016-08-09 16:06:22 +053010440struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10441 struct ieee80211_channel *channel, const u8 *bssid,
10442 const u8 *ssid, size_t ssid_len)
10443{
10444 return cfg80211_get_bss(wiphy, channel, bssid,
10445 ssid,
10446 ssid_len,
10447 IEEE80211_BSS_TYPE_ESS,
10448 IEEE80211_PRIVACY_ANY);
10449}
10450#endif
10451
10452
10453/*
10454 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10455 * interface that BSS might have been lost.
10456 * @pAdapter: adaptor
10457 * @bssid: bssid which might have been lost
10458 *
10459 * Return: bss which is unlinked from kernel cache
10460 */
10461struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10462 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010463{
10464 struct net_device *dev = pAdapter->dev;
10465 struct wireless_dev *wdev = dev->ieee80211_ptr;
10466 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467 struct cfg80211_bss *bss = NULL;
10468
Abhishek Singhc9941602016-08-09 16:06:22 +053010469 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10470 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010471 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010472 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010473 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010474 hdd_info("cfg80211_unlink_bss called for BSSID "
10475 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010476 cfg80211_unlink_bss(wiphy, bss);
10477 }
10478 return bss;
10479}
10480
Abhishek Singhc9941602016-08-09 16:06:22 +053010481
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010482/**
10483 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10484 * @pAdapter: Pointer to adapter
10485 * @bss_desc: Pointer to bss descriptor
10486 *
10487 * This function is used to inform the BSS details to nl80211 interface.
10488 *
10489 * Return: struct cfg80211_bss pointer
10490 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010491struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10492 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010493{
10494 /*
10495 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10496 * already exists in bss data base of cfg80211 for that particular BSS
10497 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10498 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10499 * As of now there is no possibility to get the mgmt(probe response)
10500 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10501 * and passing to cfg80211_inform_bss_frame.
10502 */
10503 struct net_device *dev = pAdapter->dev;
10504 struct wireless_dev *wdev = dev->ieee80211_ptr;
10505 struct wiphy *wiphy = wdev->wiphy;
10506 int chan_no = bss_desc->channelId;
10507#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10508 qcom_ie_age *qie_age = NULL;
10509 int ie_length =
10510 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10511#else
10512 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10513#endif
10514 const char *ie =
10515 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10516 unsigned int freq;
10517 struct ieee80211_channel *chan;
10518 struct ieee80211_mgmt *mgmt = NULL;
10519 struct cfg80211_bss *bss_status = NULL;
10520 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10521 int rssi = 0;
10522 hdd_context_t *pHddCtx;
10523 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010524 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010525 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010526
10527 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10528 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010529 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010530 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010531
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010532 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010533 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10534 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010535 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010536 return NULL;
10537 }
10538
10539 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10540
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010541 /* Android does not want the timestamp from the frame.
10542 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010543 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010544 mgmt->u.probe_resp.timestamp =
10545 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010546
10547 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10548 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10549
10550#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10551 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10552 /* Assuming this is the last IE, copy at the end */
10553 ie_length -= sizeof(qcom_ie_age);
10554 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10555 qie_age->element_id = QCOM_VENDOR_IE_ID;
10556 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10557 qie_age->oui_1 = QCOM_OUI1;
10558 qie_age->oui_2 = QCOM_OUI2;
10559 qie_age->oui_3 = QCOM_OUI3;
10560 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10561 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +053010562 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010563 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010564 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10565 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010566 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10567 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010568#endif
10569
10570 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10571 if (bss_desc->fProbeRsp) {
10572 mgmt->frame_control |=
10573 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10574 } else {
10575 mgmt->frame_control |=
10576 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10577 }
10578
10579 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10580 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10581 freq =
10582 ieee80211_channel_to_frequency(chan_no,
10583 IEEE80211_BAND_2GHZ);
10584 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10585 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10586 freq =
10587 ieee80211_channel_to_frequency(chan_no,
10588 IEEE80211_BAND_5GHZ);
10589 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010590 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591 kfree(mgmt);
10592 return NULL;
10593 }
10594
10595 chan = __ieee80211_get_channel(wiphy, freq);
10596 /* When the band is changed on the fly using the GUI, three things are done
10597 * 1. scan abort
10598 * 2. flush scan results from cache
10599 * 3. update the band with the new band user specified (refer to the
10600 * hdd_set_band_helper function) as part of the scan abort, message will be
10601 * queued to PE and we proceed with flushing and changinh the band.
10602 * PE will stop the scanning further and report back the results what ever
10603 * it had till now by calling the call back function.
10604 * if the time between update band and scandone call back is sufficient
10605 * enough the band change reflects in SME, SME validates the channels
10606 * and discards the channels correponding to previous band and calls back
10607 * with zero bss results. but if the time between band update and scan done
10608 * callback is very small then band change will not reflect in SME and SME
10609 * reports to HDD all the channels correponding to previous band.this is due
10610 * to race condition.but those channels are invalid to the new band and so
10611 * this function __ieee80211_get_channel will return NULL.Each time we
10612 * report scan result with this pointer null warning kernel trace is printed.
10613 * if the scan results contain large number of APs continuosly kernel
10614 * warning trace is printed and it will lead to apps watch dog bark.
10615 * So drop the bss and continue to next bss.
10616 */
10617 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010618 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10619 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010620 kfree(mgmt);
10621 return NULL;
10622 }
10623
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010624 /* Based on .ini configuration, raw rssi can be reported for bss.
10625 * Raw rssi is typically used for estimating power.
10626 */
10627
10628 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10629 bss_desc->rssi;
10630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010631 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010632 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010634 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010636 (int)(rssi / 100),
10637 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638
10639 bss_status =
10640 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10641 GFP_KERNEL);
10642 kfree(mgmt);
10643 return bss_status;
10644}
10645
10646/**
10647 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10648 * @pAdapter: Pointer to adapter
10649 * @pRoamInfo: Pointer to roam info
10650 *
10651 * This function is used to update the BSS data base of CFG8011
10652 *
10653 * Return: struct cfg80211_bss pointer
10654 */
10655struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10656 tCsrRoamInfo *pRoamInfo)
10657{
10658 tCsrRoamConnectedProfile roamProfile;
10659 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10660 struct cfg80211_bss *bss = NULL;
10661
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010662 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10663 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10664
10665 if (NULL != roamProfile.pBssDesc) {
10666 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10667 roamProfile.pBssDesc);
10668
10669 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010670 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010672 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010673 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010674 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010675 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010676 return bss;
10677}
10678/**
10679 * wlan_hdd_cfg80211_update_bss() - update bss
10680 * @wiphy: Pointer to wiphy
10681 * @pAdapter: Pointer to adapter
10682 * @scan_time: scan request timestamp
10683 *
10684 * Return: zero if success, non-zero otherwise
10685 */
10686int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10687 hdd_adapter_t *pAdapter,
10688 uint32_t scan_time)
10689{
10690 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10691 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010692 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010693 tScanResultHandle pResult;
10694 struct cfg80211_bss *bss_status = NULL;
10695 hdd_context_t *pHddCtx;
10696 int ret;
10697
10698 ENTER();
10699
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010700 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010701 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10702 NO_SESSION, pAdapter->sessionId));
10703
10704 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10705 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010706 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010707 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708
10709 /* start getting scan results and populate cgf80211 BSS database */
10710 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10711
10712 /* no scan results */
10713 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010714 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010715 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010716 }
10717
10718 pScanResult = sme_scan_result_get_first(hHal, pResult);
10719
10720 while (pScanResult) {
10721 /*
10722 * - cfg80211_inform_bss() is not updating ie field of bss
10723 * entry if entry already exists in bss data base of cfg80211
10724 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10725 * to update thebss entry instead of cfg80211_inform_bss,
10726 * But this call expects mgmt packet as input. As of now
10727 * there is no possibility to get the mgmt(probe response)
10728 * frame from PE, converting bss_desc to
10729 * ieee80211_mgmt(probe response) and passing to c
10730 * fg80211_inform_bss_frame.
10731 * - Update BSS only if beacon timestamp is later than
10732 * scan request timestamp.
10733 */
10734 if ((scan_time == 0) ||
10735 (scan_time <
10736 pScanResult->BssDescriptor.nReceivedTime)) {
10737 bss_status =
10738 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10739 &pScanResult->BssDescriptor);
10740
10741 if (NULL == bss_status) {
10742 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10743 } else {
10744 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010745 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010746 bss_status);
10747 }
10748 } else {
10749 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10750 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10751 }
10752 pScanResult = sme_scan_result_get_next(hHal, pResult);
10753 }
10754
10755 sme_scan_result_purge(hHal, pResult);
10756 /*
10757 * For SAP mode, scan is invoked by hostapd during SAP start
10758 * if hostapd is restarted, we need to flush previous scan
10759 * result so that it will reflect environment change
10760 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010761 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10763 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10764#endif
10765 )
10766 sme_scan_flush_result(hHal);
10767
10768 EXIT();
10769 return 0;
10770}
10771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010772/**
10773 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10774 * @pAdapter: Pointer to adapter
10775 * @pRoamInfo: Pointer to roam info
10776 * @index: Index
10777 * @preauth: Preauth flag
10778 *
10779 * This function is used to notify the supplicant of a new PMKSA candidate.
10780 *
10781 * Return: 0 for success, non-zero for failure
10782 */
10783int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10784 tCsrRoamInfo *pRoamInfo,
10785 int index, bool preauth)
10786{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010787 struct net_device *dev = pAdapter->dev;
10788 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10789
10790 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010791 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792
10793 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010794 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010795 return -EINVAL;
10796 }
10797
10798 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010799 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010800 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10801 cfg80211_pmksa_candidate_notify(dev, index,
10802 pRoamInfo->bssid.bytes,
10803 preauth, GFP_KERNEL);
10804 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010805 return 0;
10806}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807
10808#ifdef FEATURE_WLAN_LFR_METRICS
10809/**
10810 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10811 * @pAdapter: Pointer to adapter
10812 * @pRoamInfo: Pointer to roam info
10813 *
10814 * 802.11r/LFR metrics reporting function to report preauth initiation
10815 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010816 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010817 */
10818#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010819QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010820 tCsrRoamInfo *pRoamInfo)
10821{
10822 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10823 union iwreq_data wrqu;
10824
10825 ENTER();
10826
10827 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010828 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010829 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010830 }
10831
10832 /* create the event */
10833 memset(&wrqu, 0, sizeof(wrqu));
10834 memset(metrics_notification, 0, sizeof(metrics_notification));
10835
10836 wrqu.data.pointer = metrics_notification;
10837 wrqu.data.length = scnprintf(metrics_notification,
10838 sizeof(metrics_notification),
10839 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10840 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10841
10842 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10843 metrics_notification);
10844
10845 EXIT();
10846
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010847 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010848}
10849
10850/**
10851 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10852 * @pAdapter: Pointer to adapter
10853 * @pRoamInfo: Pointer to roam info
10854 * @preauth_status: Preauth status
10855 *
10856 * 802.11r/LFR metrics reporting function to report handover initiation
10857 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010858 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010860QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10862 tCsrRoamInfo *pRoamInfo,
10863 bool preauth_status)
10864{
10865 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10866 union iwreq_data wrqu;
10867
10868 ENTER();
10869
10870 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010871 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010872 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010873 }
10874
10875 /* create the event */
10876 memset(&wrqu, 0, sizeof(wrqu));
10877 memset(metrics_notification, 0, sizeof(metrics_notification));
10878
10879 scnprintf(metrics_notification, sizeof(metrics_notification),
10880 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10881 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10882
10883 if (1 == preauth_status)
10884 strlcat(metrics_notification, " true",
10885 sizeof(metrics_notification));
10886 else
10887 strlcat(metrics_notification, " false",
10888 sizeof(metrics_notification));
10889
10890 wrqu.data.pointer = metrics_notification;
10891 wrqu.data.length = strlen(metrics_notification);
10892
10893 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10894 metrics_notification);
10895
10896 EXIT();
10897
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010898 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899}
10900
10901/**
10902 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10903 * @pAdapter: Pointer to adapter
10904 * @pRoamInfo: Pointer to roam info
10905 *
10906 * 802.11r/LFR metrics reporting function to report handover initiation
10907 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010908 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010910QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 tCsrRoamInfo *pRoamInfo)
10912{
10913 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10914 union iwreq_data wrqu;
10915
10916 ENTER();
10917
10918 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010919 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010920 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010921 }
10922
10923 /* create the event */
10924 memset(&wrqu, 0, sizeof(wrqu));
10925 memset(metrics_notification, 0, sizeof(metrics_notification));
10926
10927 wrqu.data.pointer = metrics_notification;
10928 wrqu.data.length = scnprintf(metrics_notification,
10929 sizeof(metrics_notification),
10930 "QCOM: LFR_PREAUTH_HANDOVER "
10931 MAC_ADDRESS_STR,
10932 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10933
10934 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10935 metrics_notification);
10936
10937 EXIT();
10938
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010939 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010940}
10941#endif
10942
10943/**
10944 * hdd_select_cbmode() - select channel bonding mode
10945 * @pAdapter: Pointer to adapter
10946 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010947 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 *
10949 * Return: none
10950 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010951void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10952 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010953{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010954 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010955 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010956 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010957
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010958 /*
10959 * CDS api expects secondary channel for calculating
10960 * the channel params
10961 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010962 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010963 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
10964 if (operationChannel >= 1 && operationChannel <= 5)
10965 sec_ch = operationChannel + 4;
10966 else if (operationChannel >= 6 && operationChannel <= 13)
10967 sec_ch = operationChannel - 4;
10968 }
10969
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010971 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010972
10973 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010974 eHddDot11Mode hdd_dot11_mode;
10975 uint8_t iniDot11Mode =
10976 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
10977
10978 hdd_notice("Dot11Mode is %u", iniDot11Mode);
10979 switch (iniDot11Mode) {
10980 case eHDD_DOT11_MODE_AUTO:
10981 case eHDD_DOT11_MODE_11ac:
10982 case eHDD_DOT11_MODE_11ac_ONLY:
10983 if (sme_is_feature_supported_by_fw(DOT11AC))
10984 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
10985 else
10986 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10987 break;
10988 case eHDD_DOT11_MODE_11n:
10989 case eHDD_DOT11_MODE_11n_ONLY:
10990 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10991 break;
10992 default:
10993 hdd_dot11_mode = iniDot11Mode;
10994 break;
10995 }
10996 ch_info->channel_width = ch_params->ch_width;
10997 ch_info->phy_mode =
10998 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010999 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011000 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011001 hdd_info("ch_info width %d, phymode %d channel %d",
11002 ch_info->channel_width, ch_info->phy_mode,
11003 ch_info->channel);
11004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005}
11006
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011007/**
11008 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11009 * @adapter: STA adapter
11010 * @roam_profile: STA roam profile
11011 *
11012 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11013 *
11014 * Return: false if sta-sap conc is not allowed, else return true
11015 */
11016static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11017 tCsrRoamProfile *roam_profile)
11018{
11019 hdd_context_t *hdd_ctx;
11020 hdd_adapter_t *ap_adapter;
11021 hdd_ap_ctx_t *hdd_ap_ctx;
11022 hdd_hostapd_state_t *hostapd_state;
11023 uint8_t channel = 0;
11024 QDF_STATUS status;
11025
11026 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11027 if (!hdd_ctx) {
11028 hdd_err("HDD context is NULL");
11029 return true;
11030 }
11031
11032 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11033 /* probably no sap running, no handling required */
11034 if (ap_adapter == NULL)
11035 return true;
11036
11037 /*
11038 * sap is not in started state, so it is fine to go ahead with sta.
11039 * if sap is currently doing CAC then don't allow sta to go further.
11040 */
11041 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11042 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11043 return true;
11044
11045 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11046 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11047 return false;
11048 }
11049
11050 /*
11051 * log and return error, if we allow STA to go through, we don't
11052 * know what is going to happen better stop sta connection
11053 */
11054 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11055 if (NULL == hdd_ap_ctx) {
11056 hdd_err("AP context not found");
11057 return false;
11058 }
11059
11060 /* sap is on non-dfs channel, nothing to handle */
11061 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11062 hdd_info("sap is on non-dfs channel, sta is allowed");
11063 return true;
11064 }
11065 /*
11066 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011067 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011068 */
11069 status = cds_get_channel_from_scan_result(adapter,
11070 roam_profile, &channel);
11071
Nitesh Shah59774522016-09-16 15:14:21 +053011072 /*
11073 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11074 * channels for roaming case.
11075 */
11076 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11077 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11078 return true;
11079 }
11080
11081 /*
11082 * If channel is 0 or DFS then better to call pcl and find out the
11083 * best channel. If channel is non-dfs 5 GHz then better move SAP
11084 * to STA's channel to make scc, so we have room for 3port MCC
11085 * scenario.
11086 */
11087 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011088 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11089 true);
11090
11091 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11092 qdf_event_reset(&hostapd_state->qdf_event);
11093 status = wlansap_set_channel_change_with_csa(
11094 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11095 hdd_ap_ctx->sapConfig.ch_width_orig);
11096
11097 if (QDF_STATUS_SUCCESS != status) {
11098 hdd_err("Set channel with CSA IE failed, can't allow STA");
11099 return false;
11100 }
11101
11102 /*
11103 * wait here for SAP to finish the channel switch. When channel
11104 * switch happens, SAP sends few beacons with CSA_IE. After
11105 * successfully Transmission of those beacons, it will move its
11106 * state from started to disconnected and move to new channel.
11107 * once it moves to new channel, sap again moves its state
11108 * machine from disconnected to started and set this event.
11109 * wait for 10 secs to finish this.
11110 */
11111 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11112 if (!QDF_IS_STATUS_SUCCESS(status)) {
11113 hdd_err("wait for qdf_event failed, STA not allowed!!");
11114 return false;
11115 }
11116
11117 return true;
11118}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011119
Krunal Soni31949422016-07-29 17:17:53 -070011120/**
11121 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011122 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011123 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011124 * @ssid_len: Length of ssid
11125 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011126 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011127 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011128 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129 *
11130 * This function is used to start the association process
11131 *
11132 * Return: 0 for success, non-zero for failure
11133 */
Krunal Soni31949422016-07-29 17:17:53 -070011134static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011136 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011137 u8 operatingChannel,
11138 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139{
11140 int status = 0;
11141 hdd_wext_state_t *pWextState;
11142 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011143 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 uint32_t roamId;
11145 tCsrRoamProfile *pRoamProfile;
11146 eCsrAuthType RSNAuthType;
11147 tSmeConfigParams *sme_config;
11148
11149 ENTER();
11150
11151 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11152 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011153 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154
11155 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011156 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158
11159 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011160 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 return -EINVAL;
11162 }
11163
11164 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011165 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11166 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167
11168 if (pRoamProfile) {
11169 hdd_station_ctx_t *pHddStaCtx;
11170 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11171
11172 if (HDD_WMM_USER_MODE_NO_QOS ==
11173 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11174 /*QoS not enabled in cfg file */
11175 pRoamProfile->uapsd_mask = 0;
11176 } else {
11177 /*QoS enabled, update uapsd mask from cfg file */
11178 pRoamProfile->uapsd_mask =
11179 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11180 }
11181
11182 pRoamProfile->SSIDs.numOfSSIDs = 1;
11183 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011184 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011186 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 ssid, ssid_len);
11188
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011189 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011190 if (bssid) {
11191 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011192 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011193 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011194 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011195 /*
11196 * Save BSSID in seperate variable as
11197 * pRoamProfile's BSSID is getting zeroed out in the
11198 * association process. In case of join failure
11199 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011200 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011201 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011202 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011203 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011204 } else if (bssid_hint) {
11205 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011206 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011207 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011208 /*
11209 * Save BSSID in a separate variable as
11210 * pRoamProfile's BSSID is getting zeroed out in the
11211 * association process. In case of join failure
11212 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011213 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011214 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011215 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011216 hdd_info("bssid_hint is given by upper layer %pM",
11217 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011219 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011220 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011221 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 }
11223
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011224 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 pRoamProfile->SSIDs.SSIDList->SSID.length,
11226 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11227 operatingChannel);
11228
11229 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11230 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011231 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11233 }
11234#ifdef FEATURE_WLAN_WAPI
11235 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011236 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011237 switch (pAdapter->wapi_info.wapiAuthMode) {
11238 case WAPI_AUTH_MODE_PSK:
11239 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011240 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011241 pAdapter->wapi_info.wapiAuthMode);
11242 pRoamProfile->AuthType.authType[0] =
11243 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11244 break;
11245 }
11246 case WAPI_AUTH_MODE_CERT:
11247 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011248 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 pAdapter->wapi_info.wapiAuthMode);
11250 pRoamProfile->AuthType.authType[0] =
11251 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11252 break;
11253 }
11254 } /* End of switch */
11255 if (pAdapter->wapi_info.wapiAuthMode ==
11256 WAPI_AUTH_MODE_PSK
11257 || pAdapter->wapi_info.wapiAuthMode ==
11258 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011259 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 pRoamProfile->AuthType.numEntries = 1;
11261 pRoamProfile->EncryptionType.numEntries = 1;
11262 pRoamProfile->EncryptionType.encryptionType[0] =
11263 eCSR_ENCRYPT_TYPE_WPI;
11264 pRoamProfile->mcEncryptionType.numEntries = 1;
11265 pRoamProfile->mcEncryptionType.
11266 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11267 }
11268 }
Krunal Soni31949422016-07-29 17:17:53 -070011269#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270#ifdef WLAN_FEATURE_GTK_OFFLOAD
11271 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011272 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11273 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11275 sizeof(tSirGtkOffloadParams));
11276 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11277 GTK_OFFLOAD_DISABLE;
11278 }
11279#endif
11280 pRoamProfile->csrPersona = pAdapter->device_mode;
11281
11282 if (operatingChannel) {
11283 pRoamProfile->ChannelInfo.ChannelList =
11284 &operatingChannel;
11285 pRoamProfile->ChannelInfo.numOfChannels = 1;
11286 } else {
11287 pRoamProfile->ChannelInfo.ChannelList = NULL;
11288 pRoamProfile->ChannelInfo.numOfChannels = 0;
11289 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011290 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011291 && operatingChannel) {
11292 /*
11293 * Need to post the IBSS power save parameters
11294 * to WMA. WMA will configure this parameters
11295 * to firmware if power save is enabled by the
11296 * firmware.
11297 */
11298 status = hdd_set_ibss_power_save_params(pAdapter);
11299
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011300 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011301 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 return -EINVAL;
11303 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011304 pRoamProfile->ch_params.ch_width =
11305 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011306 /*
11307 * In IBSS mode while operating in 2.4 GHz,
11308 * the device supports only 20 MHz.
11309 */
11310 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11311 pRoamProfile->ch_params.ch_width =
11312 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011313 hdd_select_cbmode(pAdapter, operatingChannel,
11314 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011315 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011316 /*
11317 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11318 * or pmf=2 is an explicit configuration in the supplicant
11319 * configuration, drop the connection request.
11320 */
11321 if (pWextState->roamProfile.MFPEnabled &&
11322 !(pWextState->roamProfile.MFPRequired ||
11323 pWextState->roamProfile.MFPCapable)) {
11324 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11325 pWextState->roamProfile.MFPEnabled,
11326 pWextState->roamProfile.MFPRequired,
11327 pWextState->roamProfile.MFPCapable);
11328 return -EINVAL;
11329 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330
Krunal Soni3091bcc2016-06-23 12:28:21 -070011331 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011332 hdd_err("Connection refused: conn in progress");
11333 return -EINVAL;
11334 }
11335
Krunal Soni31949422016-07-29 17:17:53 -070011336 /*
11337 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011338 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011339 * enhancements, the supplicant is not issuing the scan command
11340 * now. So the unicast frames which are sent from the host are
11341 * not having the additional IEs. If it is P2P CLIENT and there
11342 * is no additional IE present in roamProfile, then use the
11343 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 */
11345
Krunal Sonib4326f22016-03-10 13:05:51 -080011346 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011347 (!pRoamProfile->pAddIEScan)) {
11348 pRoamProfile->pAddIEScan =
11349 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11350 pRoamProfile->nAddIEScanLength =
11351 pAdapter->scan_info.scanAddIE.length;
11352 }
11353 /*
11354 * When policy manager is enabled from ini file, we shouldn't
11355 * check for other concurrency rules.
11356 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011357 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011358 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011359 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360 pAdapter, pRoamProfile, &roamId))
11361 return 0;
11362 }
11363
Krunal Soni3091bcc2016-06-23 12:28:21 -070011364 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011365 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11366 pRoamProfile))) {
11367 hdd_err("sap-sta conc will fail, can't allow sta");
11368 hdd_conn_set_connection_state(pAdapter,
11369 eConnectionState_NotConnected);
11370 return -ENOMEM;
11371 }
11372
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011373 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011374 if (!sme_config) {
11375 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011376 hdd_conn_set_connection_state(pAdapter,
11377 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011378 return -ENOMEM;
11379 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011380 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381 sme_get_config_param(pHddCtx->hHal, sme_config);
11382 /* These values are not sessionized. So, any change in these SME
11383 * configs on an older or parallel interface will affect the
11384 * cb mode. So, restoring the default INI params before starting
11385 * interfaces such as sta, cli etc.,
11386 */
11387 sme_config->csrConfig.channelBondingMode5GHz =
11388 pHddCtx->config->nChannelBondingMode5GHz;
11389 sme_config->csrConfig.channelBondingMode24GHz =
11390 pHddCtx->config->nChannelBondingMode24GHz;
11391 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011392 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011393 /*
11394 * Change conn_state to connecting before sme_roam_connect(),
11395 * because sme_roam_connect() has a direct path to call
11396 * hdd_sme_roam_callback(), which will change the conn_state
11397 * If direct path, conn_state will be accordingly changed to
11398 * NotConnected or Associated by either
11399 * hdd_association_completion_handler() or
11400 * hdd_dis_connect_handler() in sme_RoamCallback()if
11401 * sme_RomConnect is to be queued,
11402 * Connecting state will remain until it is completed.
11403 *
11404 * If connection state is not changed, connection state will
11405 * remain in eConnectionState_NotConnected state.
11406 * In hdd_association_completion_handler, "hddDisconInProgress"
11407 * is set to true if conn state is
11408 * eConnectionState_NotConnected.
11409 * If "hddDisconInProgress" is set to true then cfg80211 layer
11410 * is not informed of connect result indication which
11411 * is an issue.
11412 */
11413 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011414 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011415 hdd_conn_set_connection_state(pAdapter,
11416 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417
11418 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11419 pAdapter->sessionId, pRoamProfile,
11420 &roamId);
11421
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011422 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011423 (QDF_STA_MODE == pAdapter->device_mode ||
11424 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011425 hdd_err("sme_roam_connect (session %d) failed with "
11426 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011427 pAdapter->sessionId, status);
11428 /* change back to NotAssociated */
11429 hdd_conn_set_connection_state(pAdapter,
11430 eConnectionState_NotConnected);
11431 }
11432
11433 pRoamProfile->ChannelInfo.ChannelList = NULL;
11434 pRoamProfile->ChannelInfo.numOfChannels = 0;
11435
11436 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011437 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438 return -EINVAL;
11439 }
11440 EXIT();
11441 return status;
11442}
11443
11444/**
11445 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11446 * @pAdapter: Pointer to adapter
11447 * @auth_type: Auth type
11448 *
11449 * This function is used to set the authentication type (OPEN/SHARED).
11450 *
11451 * Return: 0 for success, non-zero for failure
11452 */
11453static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11454 enum nl80211_auth_type auth_type)
11455{
11456 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11457 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 /*set authentication type */
11460 switch (auth_type) {
11461 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011462 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011463 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11464 break;
11465
11466 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011468 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11470 break;
11471
11472 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011473 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011474 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11475 break;
11476#ifdef FEATURE_WLAN_ESE
11477 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011478 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011479 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11480 break;
11481#endif
11482
11483 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011484 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011485 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11486 return -EINVAL;
11487 }
11488
11489 pWextState->roamProfile.AuthType.authType[0] =
11490 pHddStaCtx->conn_info.authType;
11491 return 0;
11492}
11493
11494/**
11495 * wlan_hdd_set_akm_suite() - set key management type
11496 * @pAdapter: Pointer to adapter
11497 * @key_mgmt: Key management type
11498 *
11499 * This function is used to set the key mgmt type(PSK/8021x).
11500 *
11501 * Return: 0 for success, non-zero for failure
11502 */
11503static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11504{
11505 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11508#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11509 /*set key mgmt type */
11510 switch (key_mgmt) {
11511 case WLAN_AKM_SUITE_PSK:
11512 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011514 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011515 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11516 break;
11517
11518 case WLAN_AKM_SUITE_8021X_SHA256:
11519 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011521 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011522 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11523 break;
11524#ifdef FEATURE_WLAN_ESE
11525#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11526#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11527 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011528 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11530 break;
11531#endif
11532#ifndef WLAN_AKM_SUITE_OSEN
11533#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11534#endif
11535 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011536 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011537 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11538 break;
11539
11540 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011541 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011542 return -EINVAL;
11543
11544 }
11545 return 0;
11546}
11547
11548/**
11549 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11550 * @pAdapter: Pointer to adapter
11551 * @cipher: Cipher type
11552 * @ucast: Unicast flag
11553 *
11554 * This function is used to set the encryption type
11555 * (NONE/WEP40/WEP104/TKIP/CCMP).
11556 *
11557 * Return: 0 for success, non-zero for failure
11558 */
11559static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11560 u32 cipher, bool ucast)
11561{
11562 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11563 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11564 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011566 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011567 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011568 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11569 } else {
11570
11571 /*set encryption method */
11572 switch (cipher) {
11573 case IW_AUTH_CIPHER_NONE:
11574 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11575 break;
11576
11577 case WLAN_CIPHER_SUITE_WEP40:
11578 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11579 break;
11580
11581 case WLAN_CIPHER_SUITE_WEP104:
11582 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11583 break;
11584
11585 case WLAN_CIPHER_SUITE_TKIP:
11586 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11587 break;
11588
11589 case WLAN_CIPHER_SUITE_CCMP:
11590 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11591 break;
11592#ifdef FEATURE_WLAN_WAPI
11593 case WLAN_CIPHER_SUITE_SMS4:
11594 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11595 break;
11596#endif
11597
11598#ifdef FEATURE_WLAN_ESE
11599 case WLAN_CIPHER_SUITE_KRK:
11600 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11601 break;
11602#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11603 case WLAN_CIPHER_SUITE_BTK:
11604 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11605 break;
11606#endif
11607#endif
11608 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011609 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011610 return -EOPNOTSUPP;
11611 }
11612 }
11613
11614 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011615 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011616 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11617 pWextState->roamProfile.EncryptionType.numEntries = 1;
11618 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11619 encryptionType;
11620 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011621 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11623 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11624 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11625 encryptionType;
11626 }
11627
11628 return 0;
11629}
11630
11631/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011632 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11633 * @wext_state: Pointer to wext state
11634 * @gen_ie: Pointer to IE data
11635 * @len: length of IE data
11636 *
11637 * Return: 0 for success, non-zero for failure
11638 */
11639static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11640 const uint8_t *gen_ie, uint16_t len)
11641{
11642 uint16_t cur_add_ie_len =
11643 wext_state->assocAddIE.length;
11644
11645 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11646 (wext_state->assocAddIE.length + len)) {
11647 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11648 QDF_ASSERT(0);
11649 return -ENOMEM;
11650 }
11651 memcpy(wext_state->assocAddIE.addIEdata +
11652 cur_add_ie_len, gen_ie, len);
11653 wext_state->assocAddIE.length += len;
11654
11655 wext_state->roamProfile.pAddIEAssoc =
11656 wext_state->assocAddIE.addIEdata;
11657 wext_state->roamProfile.nAddIEAssocLength =
11658 wext_state->assocAddIE.length;
11659 return 0;
11660}
11661
11662/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663 * wlan_hdd_cfg80211_set_ie() - set IEs
11664 * @pAdapter: Pointer to adapter
11665 * @ie: Pointer ot ie
11666 * @ie: IE length
11667 *
11668 * Return: 0 for success, non-zero for failure
11669 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011670static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 size_t ie_len)
11672{
11673 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11674 const uint8_t *genie = ie;
11675 uint16_t remLen = ie_len;
11676#ifdef FEATURE_WLAN_WAPI
11677 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11678 u16 *tmp;
11679 uint16_t akmsuiteCount;
11680 int *akmlist;
11681#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011682 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011683
11684 /* clear previous assocAddIE */
11685 pWextState->assocAddIE.length = 0;
11686 pWextState->roamProfile.bWPSAssociation = false;
11687 pWextState->roamProfile.bOSENAssociation = false;
11688
11689 while (remLen >= 2) {
11690 uint16_t eLen = 0;
11691 uint8_t elementId;
11692 elementId = *genie++;
11693 eLen = *genie++;
11694 remLen -= 2;
11695
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011696 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011697
11698 switch (elementId) {
11699 case DOT11F_EID_WPA:
11700 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 -070011701 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702 return -EINVAL;
11703 } else if (0 ==
11704 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11705 uint16_t curAddIELen =
11706 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011707 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011708
11709 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11710 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011711 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011712 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 return -ENOMEM;
11714 }
11715 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11716 memcpy(pWextState->assocAddIE.addIEdata +
11717 curAddIELen, genie - 2, eLen + 2);
11718 pWextState->assocAddIE.length += eLen + 2;
11719
11720 pWextState->roamProfile.bWPSAssociation = true;
11721 pWextState->roamProfile.pAddIEAssoc =
11722 pWextState->assocAddIE.addIEdata;
11723 pWextState->roamProfile.nAddIEAssocLength =
11724 pWextState->assocAddIE.length;
11725 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011726 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 memset(pWextState->WPARSNIE, 0,
11728 MAX_WPA_RSN_IE_LEN);
11729 memcpy(pWextState->WPARSNIE, genie - 2,
11730 (eLen + 2));
11731 pWextState->roamProfile.pWPAReqIE =
11732 pWextState->WPARSNIE;
11733 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11734 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11735 P2P_OUI_TYPE_SIZE))) {
11736 uint16_t curAddIELen =
11737 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011738 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739
11740 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11741 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011742 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011743 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 return -ENOMEM;
11745 }
11746 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11747 memcpy(pWextState->assocAddIE.addIEdata +
11748 curAddIELen, genie - 2, eLen + 2);
11749 pWextState->assocAddIE.length += eLen + 2;
11750
11751 pWextState->roamProfile.pAddIEAssoc =
11752 pWextState->assocAddIE.addIEdata;
11753 pWextState->roamProfile.nAddIEAssocLength =
11754 pWextState->assocAddIE.length;
11755 }
11756#ifdef WLAN_FEATURE_WFD
11757 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11758 WFD_OUI_TYPE_SIZE)) &&
11759 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011760 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 pAdapter->device_mode)) {
11762 uint16_t curAddIELen =
11763 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011764 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765
11766 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11767 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011768 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011769 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011770 return -ENOMEM;
11771 }
11772 /* WFD IE is saved to Additional IE ; it should
11773 * be accumulated to handle WPS IE + P2P IE +
11774 * WFD IE */
11775 memcpy(pWextState->assocAddIE.addIEdata +
11776 curAddIELen, genie - 2, eLen + 2);
11777 pWextState->assocAddIE.length += eLen + 2;
11778
11779 pWextState->roamProfile.pAddIEAssoc =
11780 pWextState->assocAddIE.addIEdata;
11781 pWextState->roamProfile.nAddIEAssocLength =
11782 pWextState->assocAddIE.length;
11783 }
11784#endif
11785 /* Appending HS 2.0 Indication Element in Assiciation Request */
11786 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11787 HS20_OUI_TYPE_SIZE))) {
11788 uint16_t curAddIELen =
11789 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011790 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791
11792 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11793 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011794 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011795 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796 return -ENOMEM;
11797 }
11798 memcpy(pWextState->assocAddIE.addIEdata +
11799 curAddIELen, genie - 2, eLen + 2);
11800 pWextState->assocAddIE.length += eLen + 2;
11801
11802 pWextState->roamProfile.pAddIEAssoc =
11803 pWextState->assocAddIE.addIEdata;
11804 pWextState->roamProfile.nAddIEAssocLength =
11805 pWextState->assocAddIE.length;
11806 }
11807 /* Appending OSEN Information Element in Assiciation Request */
11808 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11809 OSEN_OUI_TYPE_SIZE))) {
11810 uint16_t curAddIELen =
11811 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011812 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813
11814 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11815 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011816 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011817 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011818 return -ENOMEM;
11819 }
11820 memcpy(pWextState->assocAddIE.addIEdata +
11821 curAddIELen, genie - 2, eLen + 2);
11822 pWextState->assocAddIE.length += eLen + 2;
11823
11824 pWextState->roamProfile.bOSENAssociation = true;
11825 pWextState->roamProfile.pAddIEAssoc =
11826 pWextState->assocAddIE.addIEdata;
11827 pWextState->roamProfile.nAddIEAssocLength =
11828 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011829 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11830 MBO_OUI_TYPE_SIZE))){
11831 hdd_info("Set MBO IE(len %d)", eLen + 2);
11832 status = wlan_hdd_add_assoc_ie(pWextState,
11833 genie - 2, eLen + 2);
11834 if (status)
11835 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011836 } else {
11837 uint16_t add_ie_len =
11838 pWextState->assocAddIE.length;
11839
11840 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11841
11842 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11843 (pWextState->assocAddIE.length + eLen)) {
11844 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011845 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846 return -ENOMEM;
11847 }
11848
11849 memcpy(pWextState->assocAddIE.addIEdata +
11850 add_ie_len, genie - 2, eLen + 2);
11851 pWextState->assocAddIE.length += eLen + 2;
11852
11853 pWextState->roamProfile.pAddIEAssoc =
11854 pWextState->assocAddIE.addIEdata;
11855 pWextState->roamProfile.nAddIEAssocLength =
11856 pWextState->assocAddIE.length;
11857 }
11858 break;
11859 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011860 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011861 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11862 memcpy(pWextState->WPARSNIE, genie - 2,
11863 (eLen + 2));
11864 pWextState->roamProfile.pRSNReqIE =
11865 pWextState->WPARSNIE;
11866 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11867 break;
11868 /*
11869 * Appending Extended Capabilities with Interworking bit set
11870 * in Assoc Req.
11871 *
11872 * In assoc req this EXT Cap will only be taken into account if
11873 * interworkingService bit is set to 1. Currently
11874 * driver is only interested in interworkingService capability
11875 * from supplicant. If in future any other EXT Cap info is
11876 * required from supplicat, it needs to be handled while
11877 * sending Assoc Req in LIM.
11878 */
11879 case DOT11F_EID_EXTCAP:
11880 {
11881 uint16_t curAddIELen =
11882 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011883 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011884
11885 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11886 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011887 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011888 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 return -ENOMEM;
11890 }
11891 memcpy(pWextState->assocAddIE.addIEdata +
11892 curAddIELen, genie - 2, eLen + 2);
11893 pWextState->assocAddIE.length += eLen + 2;
11894
11895 pWextState->roamProfile.pAddIEAssoc =
11896 pWextState->assocAddIE.addIEdata;
11897 pWextState->roamProfile.nAddIEAssocLength =
11898 pWextState->assocAddIE.length;
11899 break;
11900 }
11901#ifdef FEATURE_WLAN_WAPI
11902 case WLAN_EID_WAPI:
11903 /* Setting WAPI Mode to ON=1 */
11904 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011905 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011906 tmp = (u16 *) ie;
11907 tmp = tmp + 2; /* Skip element Id and Len, Version */
11908 akmsuiteCount = WPA_GET_LE16(tmp);
11909 tmp = tmp + 1;
11910 akmlist = (int *)(tmp);
11911 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11912 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11913 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011914 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011915 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011916 return -EINVAL;
11917 }
11918
11919 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011920 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011921 pAdapter->wapi_info.wapiAuthMode =
11922 WAPI_AUTH_MODE_PSK;
11923 }
11924 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011925 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011926 pAdapter->wapi_info.wapiAuthMode =
11927 WAPI_AUTH_MODE_CERT;
11928 }
11929 break;
11930#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011931 case DOT11F_EID_SUPPOPERATINGCLASSES:
11932 {
11933 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11934 status = wlan_hdd_add_assoc_ie(pWextState,
11935 genie - 2, eLen + 2);
11936 if (status)
11937 return status;
11938 break;
11939 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011941 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942 /* when Unknown IE is received we should break and continue
11943 * to the next IE in the buffer instead we were returning
11944 * so changing this to break */
11945 break;
11946 }
11947 genie += eLen;
11948 remLen -= eLen;
11949 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011950 return 0;
11951}
11952
11953/**
11954 * hdd_is_wpaie_present() - check for WPA ie
11955 * @ie: Pointer to ie
11956 * @ie_len: Ie length
11957 *
11958 * Parse the received IE to find the WPA IE
11959 *
11960 * Return: true if wpa ie is found else false
11961 */
11962static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
11963{
11964 uint8_t eLen = 0;
11965 uint16_t remLen = ie_len;
11966 uint8_t elementId = 0;
11967
11968 while (remLen >= 2) {
11969 elementId = *ie++;
11970 eLen = *ie++;
11971 remLen -= 2;
11972 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011973 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 return false;
11975 }
11976 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
11977 /* OUI - 0x00 0X50 0XF2
11978 * WPA Information Element - 0x01
11979 * WPA version - 0x01
11980 */
11981 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
11982 return true;
11983 }
11984 ie += eLen;
11985 remLen -= eLen;
11986 }
11987 return false;
11988}
11989
11990/**
11991 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
11992 * @pAdapter: Pointer to adapter
11993 * @req: Pointer to security parameters
11994 *
11995 * Return: 0 for success, non-zero for failure
11996 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011997static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
11998 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011999{
12000 int status = 0;
12001 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12002 ENTER();
12003
12004 /*set wpa version */
12005 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12006
12007 if (req->crypto.wpa_versions) {
12008 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12009 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12010 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12011 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12012 }
12013 }
12014
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012015 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012016
12017 /*set authentication type */
12018 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12019
12020 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012021 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012022 return status;
12023 }
12024
12025 /*set key mgmt type */
12026 if (req->crypto.n_akm_suites) {
12027 status =
12028 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12029 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012030 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031 return status;
12032 }
12033 }
12034
12035 /*set pairwise cipher type */
12036 if (req->crypto.n_ciphers_pairwise) {
12037 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12038 req->crypto.
12039 ciphers_pairwise[0],
12040 true);
12041 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012042 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 return status;
12044 }
12045 } else {
12046 /*Reset previous cipher suite to none */
12047 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12048 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012049 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012050 return status;
12051 }
12052 }
12053
12054 /*set group cipher type */
12055 status =
12056 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12057 false);
12058
12059 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012060 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 return status;
12062 }
12063#ifdef WLAN_FEATURE_11W
12064 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12065#endif
12066
12067 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12068 if (req->ie_len) {
12069 status =
12070 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12071 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012072 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012073 return status;
12074 }
12075 }
12076
12077 /*incase of WEP set default key information */
12078 if (req->key && req->key_len) {
12079 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12080 || (WLAN_CIPHER_SUITE_WEP104 ==
12081 req->crypto.ciphers_pairwise[0])
12082 ) {
12083 if (IW_AUTH_KEY_MGMT_802_1X
12084 ==
12085 (pWextState->
12086 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012087 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012088 return -EOPNOTSUPP;
12089 } else {
12090 u8 key_len = req->key_len;
12091 u8 key_idx = req->key_idx;
12092
12093 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12094 key_len)
12095 && (CSR_MAX_NUM_KEY > key_idx)
12096 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012097 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012099 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 Keys.
12101 KeyMaterial[key_idx][0],
12102 req->key, key_len);
12103 pWextState->roamProfile.Keys.
12104 KeyLength[key_idx] = (u8) key_len;
12105 pWextState->roamProfile.Keys.
12106 defaultIndex = (u8) key_idx;
12107 }
12108 }
12109 }
12110 }
12111
12112 return status;
12113}
12114
12115/**
12116 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12117 * @pAdapter: Pointer to adapter
12118 *
12119 * This function is used to disconnect from previous connection
12120 *
12121 * Return: 0 for success, non-zero for failure
12122 */
12123static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12124{
12125 unsigned long rc;
12126 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012127 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012128
12129 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12130
Jeff Johnson9edf9572016-10-03 15:24:49 -070012131 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012132 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12133 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12134 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012135 hdd_conn_set_connection_state(pAdapter,
12136 eConnectionState_Disconnecting);
12137 /* Issue disconnect to CSR */
12138 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012139
12140 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12141 pAdapter->sessionId,
12142 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12143 /*
12144 * Wait here instead of returning directly, this will block the
12145 * next connect command and allow processing of the scan for
12146 * ssid and the previous connect command in CSR. Else we might
12147 * hit some race conditions leading to SME and HDD out of sync.
12148 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012149 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012150 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12151 } else if (0 != status) {
12152 hdd_err("csrRoamDisconnect failure, returned %d",
12153 (int)status);
12154 pHddStaCtx->staDebugState = status;
12155 result = -EINVAL;
12156 goto disconnected;
12157 }
12158
12159 rc = wait_for_completion_timeout(
12160 &pAdapter->disconnect_comp_var,
12161 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012162 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012163 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12164 pAdapter->sessionId, pHddStaCtx->staDebugState);
12165 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012166 }
12167 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012168 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012170 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012171 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012172 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012174 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012175 }
12176 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012177disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012178 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12179 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180}
12181
12182/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012183 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12184 * @adapter: Pointer to the HDD adapter
12185 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012186 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012187 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012188 * This function will start reassociation if prev_bssid is set and bssid/
12189 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012190 *
Naveen Rawat07332902016-07-27 09:13:17 -070012191 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012192 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012193#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12194 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012195static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12196 struct cfg80211_connect_params *req,
12197 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012198{
Naveen Rawat07332902016-07-27 09:13:17 -070012199 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012200 const uint8_t *bssid = NULL;
12201 uint16_t channel = 0;
12202
12203 if (req->bssid)
12204 bssid = req->bssid;
12205 else if (req->bssid_hint)
12206 bssid = req->bssid_hint;
12207
12208 if (req->channel)
12209 channel = req->channel->hw_value;
12210 else if (req->channel_hint)
12211 channel = req->channel_hint->hw_value;
12212
12213 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012214 reassoc = true;
12215 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012216 channel, MAC_ADDR_ARRAY(bssid));
12217 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012218 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012219 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012220 }
Naveen Rawat07332902016-07-27 09:13:17 -070012221 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012222}
12223#else
Naveen Rawat07332902016-07-27 09:13:17 -070012224static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12225 struct cfg80211_connect_params *req,
12226 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012227{
Naveen Rawat07332902016-07-27 09:13:17 -070012228 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012229}
12230#endif
12231
12232/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12234 * @wiphy: Pointer to wiphy
12235 * @dev: Pointer to network device
12236 * @req: Pointer to cfg80211 connect request
12237 *
12238 * This function is used to start the association process
12239 *
12240 * Return: 0 for success, non-zero for failure
12241 */
12242static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12243 struct net_device *ndev,
12244 struct cfg80211_connect_params *req)
12245{
12246 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012247 u16 channel;
12248#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12249 const u8 *bssid_hint = req->bssid_hint;
12250#else
12251 const u8 *bssid_hint = NULL;
12252#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012253 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12254 hdd_context_t *pHddCtx;
12255
12256 ENTER();
12257
Anurag Chouhan6d760662016-02-20 16:05:43 +053012258 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012259 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012260 return -EINVAL;
12261 }
12262
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012263 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012264 TRACE_CODE_HDD_CFG80211_CONNECT,
12265 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012266 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012267 hdd_device_mode_to_string(pAdapter->device_mode),
12268 pAdapter->device_mode);
12269
Krunal Sonib4326f22016-03-10 13:05:51 -080012270 if (pAdapter->device_mode != QDF_STA_MODE &&
12271 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012272 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012273 hdd_device_mode_to_string(pAdapter->device_mode),
12274 pAdapter->device_mode);
12275 return -EINVAL;
12276 }
12277
12278 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12279 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012280 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012281 return -EINVAL;
12282 }
12283
12284 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012285 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012286 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012287
Naveen Rawat07332902016-07-27 09:13:17 -070012288 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012289 return status;
12290
Agrawal Ashishf156e942016-08-04 14:54:47 +053012291 wlan_hdd_disable_roaming(pAdapter);
12292
12293 /* Try disconnecting if already in connected state */
12294 status = wlan_hdd_try_disconnect(pAdapter);
12295 if (0 > status) {
12296 hdd_err("Failed to disconnect the existing connection");
12297 return -EALREADY;
12298 }
12299
12300 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012302 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012303 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012304 pAdapter->device_mode),
12305 req->channel->hw_value, HW_MODE_20_MHZ)) {
12306 hdd_err("This concurrency combination is not allowed");
12307 return -ECONNREFUSED;
12308 }
12309 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012310 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012311 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012312 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12313 hdd_err("This concurrency combination is not allowed");
12314 return -ECONNREFUSED;
12315 }
12316 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012317
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012318 /*initialise security parameters */
12319 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12320
12321 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012322 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012323 return status;
12324 }
12325
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012326 if (req->channel)
12327 channel = req->channel->hw_value;
12328 else
12329 channel = 0;
12330 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12331 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012332 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012334 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012335 return status;
12336 }
12337 EXIT();
12338 return status;
12339}
12340
12341/**
12342 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12343 * @wiphy: Pointer to wiphy
12344 * @dev: Pointer to network device
12345 * @req: Pointer to cfg80211 connect request
12346 *
12347 * Return: 0 for success, non-zero for failure
12348 */
12349static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12350 struct net_device *ndev,
12351 struct cfg80211_connect_params *req)
12352{
12353 int ret;
12354 cds_ssr_protect(__func__);
12355 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12356 cds_ssr_unprotect(__func__);
12357
12358 return ret;
12359}
12360
12361/**
12362 * wlan_hdd_disconnect() - hdd disconnect api
12363 * @pAdapter: Pointer to adapter
12364 * @reason: Disconnect reason code
12365 *
12366 * This function is used to issue a disconnect request to SME
12367 *
12368 * Return: 0 for success, non-zero for failure
12369 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012370static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371{
12372 int status, result = 0;
12373 unsigned long rc;
12374 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12375 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12376
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012377 ENTER();
12378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 status = wlan_hdd_validate_context(pHddCtx);
12380
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012381 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012382 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383
12384 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012385 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12387 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012388 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12390 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12391
12392 /*issue disconnect */
12393
12394 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12395 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012396 /*
12397 * Wait here instead of returning directly, this will block the next
12398 * connect command and allow processing of the scan for ssid and
12399 * the previous connect command in CSR. Else we might hit some
12400 * race conditions leading to SME and HDD out of sync.
12401 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012402 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012403 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012405 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 (int)status);
12407 pHddStaCtx->staDebugState = status;
12408 result = -EINVAL;
12409 goto disconnected;
12410 }
12411 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12412 msecs_to_jiffies
12413 (WLAN_WAIT_TIME_DISCONNECT));
12414
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012415 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012416 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 result = -ETIMEDOUT;
12418 }
12419disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012420 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12421#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12422 /* Sending disconnect event to userspace for kernel version < 3.11
12423 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12424 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012425 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012426 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12427 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428#endif
12429
12430 return result;
12431}
12432
12433/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012434 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12435 * @reason: ieee80211 reason code.
12436 *
12437 * This utility function helps log string conversion of reason code.
12438 *
12439 * Return: string conversion of reason code, if match found;
12440 * "Unknown" otherwise.
12441 */
12442static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12443{
12444 switch (reason) {
12445 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12446 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12447 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12448 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12449 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12450 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12451 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12452 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12453 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12454 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12455 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12456 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12457 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12458 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12459 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12460 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12461 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12462 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12463 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12464 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12465 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12466 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12467 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12468 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12469 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12470 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12471 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12472 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12473 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12474 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12475 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12476 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12477 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12478 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12479 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12480 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12481 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12482 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12483 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12484 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12485 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12486 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12487 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12488 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12489 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12490 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12491 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12492 default:
12493 return "Unknown";
12494 }
12495}
12496
12497/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012498 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12499 * @wiphy: Pointer to wiphy
12500 * @dev: Pointer to network device
12501 * @reason: Disconnect reason code
12502 *
12503 * This function is used to issue a disconnect request to SME
12504 *
12505 * Return: 0 for success, non-zero for failure
12506 */
12507static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12508 struct net_device *dev, u16 reason)
12509{
12510 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12511 int status;
12512 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12513 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12514#ifdef FEATURE_WLAN_TDLS
12515 uint8_t staIdx;
12516#endif
12517
12518 ENTER();
12519
Anurag Chouhan6d760662016-02-20 16:05:43 +053012520 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012521 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 return -EINVAL;
12523 }
12524
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012525 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012526 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12527 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012528 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529 hdd_device_mode_to_string(pAdapter->device_mode),
12530 pAdapter->device_mode, reason);
12531
12532 status = wlan_hdd_validate_context(pHddCtx);
12533
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012534 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012535 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536
12537 /* Issue disconnect request to SME, if station is in connected state */
12538 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12539 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12540 eCsrRoamDisconnectReason reasonCode =
12541 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12542 hdd_scaninfo_t *pScanInfo;
12543
12544 switch (reason) {
12545 case WLAN_REASON_MIC_FAILURE:
12546 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12547 break;
12548
12549 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12550 case WLAN_REASON_DISASSOC_AP_BUSY:
12551 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12552 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12553 break;
12554
12555 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12556 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12557 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12558 break;
12559
12560 case WLAN_REASON_DEAUTH_LEAVING:
12561 reasonCode =
12562 pHddCtx->config->
12563 gEnableDeauthToDisassocMap ?
12564 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12565 eCSR_DISCONNECT_REASON_DEAUTH;
12566 break;
12567 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12568 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12569 break;
12570 default:
12571 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12572 break;
12573 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012574 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012576 pScanInfo = &pAdapter->scan_info;
12577 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012578 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12580 eCSR_SCAN_ABORT_DEFAULT);
12581 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012582 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583#ifdef FEATURE_WLAN_TDLS
12584 /* First clean up the tdls peers if any */
12585 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12586 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12587 pAdapter->sessionId)
12588 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12589 uint8_t *mac;
12590 mac =
12591 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012592 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12593 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012594 pHddCtx->tdlsConnInfo[staIdx].staId,
12595 pAdapter->sessionId,
12596 MAC_ADDR_ARRAY(mac));
12597 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12598 (pAdapter),
12599 pAdapter->sessionId, mac);
12600 }
12601 }
12602#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012603 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012604 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012605 hdd_info("Disconnect request from user space with reason: %s",
12606 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12608 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012609 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 return -EINVAL;
12611 }
12612 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012613 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012614 pHddStaCtx->conn_info.connState);
12615 }
12616
12617 return status;
12618}
12619
12620/**
12621 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12622 * @wiphy: Pointer to wiphy
12623 * @dev: Pointer to network device
12624 * @reason: Disconnect reason code
12625 *
12626 * Return: 0 for success, non-zero for failure
12627 */
12628static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12629 struct net_device *dev, u16 reason)
12630{
12631 int ret;
12632 cds_ssr_protect(__func__);
12633 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12634 cds_ssr_unprotect(__func__);
12635
12636 return ret;
12637}
12638
12639/**
12640 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12641 * @pAdapter: Pointer to adapter
12642 * @param: Pointer to IBSS parameters
12643 *
12644 * This function is used to initialize the security settings in IBSS mode
12645 *
12646 * Return: 0 for success, non-zero for failure
12647 */
12648static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12649 struct cfg80211_ibss_params
12650 *params)
12651{
12652 int status = 0;
12653 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12654 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12655 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12656
12657 ENTER();
12658
12659 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012660 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661 pHddStaCtx->ibss_enc_key_installed = 0;
12662
12663 if (params->ie_len && (NULL != params->ie)) {
12664 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12665 params->ie_len, WLAN_EID_RSN)) {
12666 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12667 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12668 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12669 tDot11fIEWPA dot11WPAIE;
12670 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12671 u8 *ie;
12672
12673 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12674 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12675 params->ie_len,
12676 DOT11F_EID_WPA);
12677 if (NULL != ie) {
12678 pWextState->wpaVersion =
12679 IW_AUTH_WPA_VERSION_WPA;
12680 /* Unpack the WPA IE */
12681 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12682 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12683 &ie[2 + 4],
12684 ie[1] - 4, &dot11WPAIE);
12685 /*Extract the multicast cipher, the encType for unicast
12686 cipher for wpa-none is none */
12687 encryptionType =
12688 hdd_translate_wpa_to_csr_encryption_type
12689 (dot11WPAIE.multicast_cipher);
12690 }
12691 }
12692
12693 status =
12694 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12695 params->ie_len);
12696
12697 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012698 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012699 return status;
12700 }
12701 }
12702
12703 pWextState->roamProfile.AuthType.authType[0] =
12704 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12705
12706 if (params->privacy) {
12707 /* Security enabled IBSS, At this time there is no information
12708 * available about the security paramters, so initialise the
12709 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12710 * The correct security parameters will be updated later in
12711 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12712 * set inorder enable privacy bit in beacons
12713 */
12714
12715 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12716 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012717 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12719 pWextState->roamProfile.EncryptionType.numEntries = 1;
12720 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12721 encryptionType;
12722 return status;
12723}
12724
12725/**
12726 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12727 * @wiphy: Pointer to wiphy
12728 * @dev: Pointer to network device
12729 * @param: Pointer to IBSS join parameters
12730 *
12731 * This function is used to create/join an IBSS network
12732 *
12733 * Return: 0 for success, non-zero for failure
12734 */
12735static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12736 struct net_device *dev,
12737 struct cfg80211_ibss_params *params)
12738{
12739 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12740 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12741 tCsrRoamProfile *pRoamProfile;
12742 int status;
12743 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12744 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012745 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012746 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747
12748 ENTER();
12749
Anurag Chouhan6d760662016-02-20 16:05:43 +053012750 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012751 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012752 return -EINVAL;
12753 }
12754
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012755 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12757 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012758 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759 hdd_device_mode_to_string(pAdapter->device_mode),
12760 pAdapter->device_mode);
12761
12762 status = wlan_hdd_validate_context(pHddCtx);
12763
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012764 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012766
12767 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012768 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12770 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12771 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12772 int indx;
12773
12774 /* Get channel number */
12775 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012776 params->
12777 chandef.
12778 chan->
12779 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780
12781 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12782 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012783 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 return -EOPNOTSUPP;
12785 }
12786
12787 for (indx = 0; indx < numChans; indx++) {
12788 if (channelNum == validChan[indx]) {
12789 break;
12790 }
12791 }
12792 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012793 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794 return -EINVAL;
12795 }
12796 }
12797
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012798 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012799 HW_MODE_20_MHZ)) {
12800 hdd_err("This concurrency combination is not allowed");
12801 return -ECONNREFUSED;
12802 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012803
Krunal Soni3091bcc2016-06-23 12:28:21 -070012804 status = qdf_reset_connection_update();
12805 if (!QDF_IS_STATUS_SUCCESS(status))
12806 hdd_err("ERR: clear event failed");
12807
12808 status = cds_current_connections_update(pAdapter->sessionId,
12809 channelNum,
12810 SIR_UPDATE_REASON_JOIN_IBSS);
12811 if (QDF_STATUS_E_FAILURE == status) {
12812 hdd_err("ERROR: connections update failed!!");
12813 return -EINVAL;
12814 }
12815
12816 if (QDF_STATUS_SUCCESS == status) {
12817 status = qdf_wait_for_connection_update();
12818 if (!QDF_IS_STATUS_SUCCESS(status)) {
12819 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820 return -EINVAL;
12821 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822 }
12823
12824 /*Try disconnecting if already in connected state */
12825 status = wlan_hdd_try_disconnect(pAdapter);
12826 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012827 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012828 return -EALREADY;
12829 }
12830
12831 pRoamProfile = &pWextState->roamProfile;
12832
12833 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012834 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012835 return -EINVAL;
12836 }
12837
12838 /* enable selected protection checks in IBSS mode */
12839 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12840
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012841 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12843 pHddCtx->config->
12844 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012845 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846 }
12847
12848 /* BSSID is provided by upper layers hence no need to AUTO generate */
12849 if (NULL != params->bssid) {
12850 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012851 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012852 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012853 return -EIO;
12854 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012855 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012856 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12857 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012858 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012859 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012860 return -EIO;
12861 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012862 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012863 }
12864 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12865 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12866 pRoamProfile->beaconInterval = params->beacon_interval;
12867 else {
12868 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012869 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 params->beacon_interval, pRoamProfile->beaconInterval);
12871 }
12872
12873 /* Set Channel */
12874 if (channelNum) {
12875 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012876 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877 pRoamProfile->ChannelInfo.numOfChannels = 1;
12878 pHddStaCtx->conn_info.operationChannel = channelNum;
12879 pRoamProfile->ChannelInfo.ChannelList =
12880 &pHddStaCtx->conn_info.operationChannel;
12881 }
12882
12883 /* Initialize security parameters */
12884 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12885 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012886 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012887 return status;
12888 }
12889
12890 /* Issue connect start */
12891 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12892 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012893 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012894 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012895 operationChannel,
12896 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012897
12898 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012899 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 return status;
12901 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012902 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 return 0;
12904}
12905
12906/**
12907 * wlan_hdd_cfg80211_join_ibss() - join ibss
12908 * @wiphy: Pointer to wiphy
12909 * @dev: Pointer to network device
12910 * @param: Pointer to IBSS join parameters
12911 *
12912 * This function is used to create/join an IBSS network
12913 *
12914 * Return: 0 for success, non-zero for failure
12915 */
12916static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12917 struct net_device *dev,
12918 struct cfg80211_ibss_params *params)
12919{
12920 int ret = 0;
12921
12922 cds_ssr_protect(__func__);
12923 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12924 cds_ssr_unprotect(__func__);
12925
12926 return ret;
12927}
12928
12929/**
12930 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12931 * @wiphy: Pointer to wiphy
12932 * @dev: Pointer to network device
12933 *
12934 * This function is used to leave an IBSS network
12935 *
12936 * Return: 0 for success, non-zero for failure
12937 */
12938static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12939 struct net_device *dev)
12940{
12941 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12942 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12943 tCsrRoamProfile *pRoamProfile;
12944 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12945 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012946 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012947 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012948 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949
12950 ENTER();
12951
Anurag Chouhan6d760662016-02-20 16:05:43 +053012952 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012953 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012954 return -EINVAL;
12955 }
12956
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012957 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12959 pAdapter->sessionId,
12960 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12961 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012962 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012963 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012964
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012965 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012966 hdd_device_mode_to_string(pAdapter->device_mode),
12967 pAdapter->device_mode);
12968 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012969 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 return -EIO;
12971 }
12972
12973 pRoamProfile = &pWextState->roamProfile;
12974
12975 /* Issue disconnect only if interface type is set to IBSS */
12976 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012977 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012978 return -EINVAL;
12979 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012980 /* Clearing add IE of beacon */
12981 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
12982 sizeof(tSirMacAddr));
12983 updateIE.smeSessionId = pAdapter->sessionId;
12984 updateIE.ieBufferlength = 0;
12985 updateIE.pAdditionIEBuffer = NULL;
12986 updateIE.append = true;
12987 updateIE.notify = true;
12988 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
12989 &updateIE,
12990 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012991 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012992 }
12993
12994 /* Reset WNI_CFG_PROBE_RSP Flags */
12995 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012996
12997 /* Issue Disconnect request */
12998 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12999 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13000 pAdapter->sessionId,
13001 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013002 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013003 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 hal_status);
13005 return -EAGAIN;
13006 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013007
13008 /* wait for mc thread to cleanup and then return to upper stack
13009 * so by the time upper layer calls the change interface, we are
13010 * all set to proceed further
13011 */
13012 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13013 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13014 if (!rc) {
13015 hdd_err("Failed to disconnect, timed out");
13016 return -ETIMEDOUT;
13017 }
13018
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013019 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020 return 0;
13021}
13022
13023/**
13024 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13025 * @wiphy: Pointer to wiphy
13026 * @dev: Pointer to network device
13027 *
13028 * This function is used to leave an IBSS network
13029 *
13030 * Return: 0 for success, non-zero for failure
13031 */
13032static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13033 struct net_device *dev)
13034{
13035 int ret = 0;
13036
13037 cds_ssr_protect(__func__);
13038 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13039 cds_ssr_unprotect(__func__);
13040
13041 return ret;
13042}
13043
13044/**
13045 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13046 * @wiphy: Pointer to wiphy
13047 * @changed: Parameters changed
13048 *
13049 * This function is used to set the phy parameters. RTS Threshold/FRAG
13050 * Threshold/Retry Count etc.
13051 *
13052 * Return: 0 for success, non-zero for failure
13053 */
13054static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13055 u32 changed)
13056{
13057 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13058 tHalHandle hHal = pHddCtx->hHal;
13059 int status;
13060
13061 ENTER();
13062
Anurag Chouhan6d760662016-02-20 16:05:43 +053013063 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013064 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 return -EINVAL;
13066 }
13067
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013068 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013069 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13070 NO_SESSION, wiphy->rts_threshold));
13071 status = wlan_hdd_validate_context(pHddCtx);
13072
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013073 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075
13076 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13077 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13078 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13079
13080 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13081 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013082 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013083 rts_threshold);
13084 return -EINVAL;
13085 }
13086
13087 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13088 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013089 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 rts_threshold);
13091 return -EIO;
13092 }
13093
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013094 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013095 }
13096
13097 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13098 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13099 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13100 wiphy->frag_threshold;
13101
13102 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13103 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013104 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 frag_threshold);
13106 return -EINVAL;
13107 }
13108
13109 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13110 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013111 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 frag_threshold);
13113 return -EIO;
13114 }
13115
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013116 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013117 }
13118
13119 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13120 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13121 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13122 wiphy->retry_short : wiphy->retry_long;
13123
13124 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13125 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013126 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013127 return -EINVAL;
13128 }
13129
13130 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13131 if (0 != sme_cfg_set_int(hHal,
13132 WNI_CFG_LONG_RETRY_LIMIT,
13133 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013134 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013135 retry_value);
13136 return -EIO;
13137 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013138 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13140 if (0 != sme_cfg_set_int(hHal,
13141 WNI_CFG_SHORT_RETRY_LIMIT,
13142 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013143 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 retry_value);
13145 return -EIO;
13146 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013147 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 }
13149 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013150 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013151 return 0;
13152}
13153
13154/**
13155 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13156 * @wiphy: Pointer to wiphy
13157 * @changed: Parameters changed
13158 *
13159 * Return: 0 for success, non-zero for failure
13160 */
13161static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13162{
13163 int ret;
13164
13165 cds_ssr_protect(__func__);
13166 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13167 cds_ssr_unprotect(__func__);
13168
13169 return ret;
13170}
13171
13172/**
13173 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13174 * key
13175 * @wiphy: Pointer to wiphy
13176 * @dev: Pointer to network device
13177 * @key_index: Key index
13178 *
13179 * Return: 0
13180 */
13181static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13182 struct net_device *netdev,
13183 u8 key_index)
13184{
13185 ENTER();
13186 return 0;
13187}
13188
13189/**
13190 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13191 * wlan_hdd_set_default_mgmt_key
13192 * @wiphy: pointer to wiphy
13193 * @netdev: pointer to net_device structure
13194 * @key_index: key index
13195 *
13196 * Return: 0 on success, error number on failure
13197 */
13198static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13199 struct net_device *netdev,
13200 u8 key_index)
13201{
13202 int ret;
13203
13204 cds_ssr_protect(__func__);
13205 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13206 cds_ssr_unprotect(__func__);
13207
13208 return ret;
13209}
13210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211/**
13212 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13213 * @wiphy: Pointer to wiphy
13214 * @dev: Pointer to network device
13215 * @params: Pointer to tx queue parameters
13216 *
13217 * Return: 0
13218 */
13219static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13220 struct net_device *dev,
13221 struct ieee80211_txq_params *params)
13222{
13223 ENTER();
13224 return 0;
13225}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013226
13227/**
13228 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13229 * @wiphy: pointer to wiphy
13230 * @netdev: pointer to net_device structure
13231 * @params: pointer to ieee80211_txq_params
13232 *
13233 * Return: 0 on success, error number on failure
13234 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013235static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13236 struct net_device *dev,
13237 struct ieee80211_txq_params *params)
13238{
13239 int ret;
13240
13241 cds_ssr_protect(__func__);
13242 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13243 cds_ssr_unprotect(__func__);
13244
13245 return ret;
13246}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247
13248/**
13249 * __wlan_hdd_cfg80211_del_station() - delete station v2
13250 * @wiphy: Pointer to wiphy
13251 * @param: Pointer to delete station parameter
13252 *
13253 * Return: 0 for success, non-zero for failure
13254 */
13255static
13256int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13257 struct net_device *dev,
13258 struct tagCsrDelStaParams *pDelStaParams)
13259{
13260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13261 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013262 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 hdd_hostapd_state_t *hapd_state;
13264 int status;
13265 uint8_t staId;
13266 uint8_t *mac;
13267
13268 ENTER();
13269
Anurag Chouhan6d760662016-02-20 16:05:43 +053013270 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013271 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 return -EINVAL;
13273 }
13274
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013275 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013276 TRACE_CODE_HDD_CFG80211_DEL_STA,
13277 pAdapter->sessionId, pAdapter->device_mode));
13278
13279 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13280 status = wlan_hdd_validate_context(pHddCtx);
13281
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013282 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284
13285 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13286
Krunal Sonib4326f22016-03-10 13:05:51 -080013287 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13288 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289
13290 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13291 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013292 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013293 return 0;
13294 }
13295
Anurag Chouhanc5548422016-02-24 18:33:27 +053013296 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013297 uint16_t i;
13298 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13299 if ((pAdapter->aStaInfo[i].isUsed) &&
13300 (!pAdapter->aStaInfo[i].
13301 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013302 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303 mac,
13304 pAdapter->aStaInfo[i].
13305 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013306 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13308 hdd_ipa_wlan_evt(pAdapter,
13309 pAdapter->
13310 aStaInfo[i].
13311 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013312 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013313 mac);
13314 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013315 hdd_notice("Delete STA with MAC::"
13316 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013317 MAC_ADDR_ARRAY(mac));
13318
13319 if (pHddCtx->dev_dfs_cac_status ==
13320 DFS_CAC_IN_PROGRESS)
13321 goto fn_end;
13322
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013323 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013325 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013326 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013327 hdd_softap_sta_deauth(pAdapter,
13328 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013329 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013330 pAdapter->aStaInfo[i].
13331 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013332 qdf_status =
13333 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013334 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013336 if (!QDF_IS_STATUS_SUCCESS(
13337 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013338 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013339 }
13340 }
13341 }
13342 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013343 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013344 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013345 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013347 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013348 hdd_notice("Skip DEL STA as this is not used::"
13349 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350 MAC_ADDR_ARRAY(mac));
13351 return -ENOENT;
13352 }
13353
13354 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13355 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013356 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013357 }
13358
13359 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13360 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013361 hdd_notice("Skip DEL STA as deauth is in progress::"
13362 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013363 MAC_ADDR_ARRAY(mac));
13364 return -ENOENT;
13365 }
13366
13367 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13368
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013369 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370 MAC_ADDR_ARRAY(mac));
13371
13372 /* Case: SAP in ACS selected DFS ch and client connected
13373 * Now Radar detected. Then if random channel is another
13374 * DFS ch then new CAC is initiated and no TX allowed.
13375 * So do not send any mgmt frames as it will timeout
13376 * during CAC.
13377 */
13378
13379 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13380 goto fn_end;
13381
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013382 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013383 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13384 (pAdapter), pAdapter->sessionId,
13385 (uint8_t *)&pDelStaParams->peerMacAddr,
13386 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013387 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013388 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013389 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013390 pAdapter->aStaInfo[staId].isDeauthInProgress =
13391 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013392 hdd_notice("STA removal failed for ::"
13393 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 MAC_ADDR_ARRAY(mac));
13395 return -ENOENT;
13396 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013397 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013398 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013399 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013400 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013401 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 }
13403 }
13404 }
13405
13406fn_end:
13407 EXIT();
13408 return 0;
13409}
13410
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013411#if defined(USE_CFG80211_DEL_STA_V2)
13412/**
13413 * wlan_hdd_del_station() - delete station wrapper
13414 * @adapter: pointer to the hdd adapter
13415 *
13416 * Return: None
13417 */
13418void wlan_hdd_del_station(hdd_adapter_t *adapter)
13419{
13420 struct station_del_parameters del_sta;
13421 del_sta.mac = NULL;
13422 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13423 del_sta.reason_code = eCsrForcedDeauthSta;
13424
13425 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13426 &del_sta);
13427}
13428#else
13429void wlan_hdd_del_station(hdd_adapter_t *adapter)
13430{
13431 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13432}
13433#endif
13434
13435#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013436/**
13437 * wlan_hdd_cfg80211_del_station() - delete station v2
13438 * @wiphy: Pointer to wiphy
13439 * @param: Pointer to delete station parameter
13440 *
13441 * Return: 0 for success, non-zero for failure
13442 */
13443int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13444 struct net_device *dev,
13445 struct station_del_parameters *param)
13446#else
13447/**
13448 * wlan_hdd_cfg80211_del_station() - delete station
13449 * @wiphy: Pointer to wiphy
13450 * @mac: Pointer to station mac address
13451 *
13452 * Return: 0 for success, non-zero for failure
13453 */
13454#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13455int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13456 struct net_device *dev,
13457 const uint8_t *mac)
13458#else
13459int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13460 struct net_device *dev,
13461 uint8_t *mac)
13462#endif
13463#endif
13464{
13465 int ret;
13466 struct tagCsrDelStaParams delStaParams;
13467
13468 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013469#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013471 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013472 return -EINVAL;
13473 }
13474 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13475 param->subtype, &delStaParams);
13476#else
13477 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13478 (SIR_MAC_MGMT_DEAUTH >> 4),
13479 &delStaParams);
13480#endif
13481 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13482 cds_ssr_unprotect(__func__);
13483
13484 return ret;
13485}
13486
13487/**
13488 * __wlan_hdd_cfg80211_add_station() - add station
13489 * @wiphy: Pointer to wiphy
13490 * @mac: Pointer to station mac address
13491 * @pmksa: Pointer to add station parameter
13492 *
13493 * Return: 0 for success, non-zero for failure
13494 */
13495static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13496 struct net_device *dev,
13497 const uint8_t *mac,
13498 struct station_parameters *params)
13499{
13500 int status = -EPERM;
13501#ifdef FEATURE_WLAN_TDLS
13502 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13503 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13504 u32 mask, set;
13505
13506 ENTER();
13507
Anurag Chouhan6d760662016-02-20 16:05:43 +053013508 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013509 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013510 return -EINVAL;
13511 }
13512
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013513 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013514 TRACE_CODE_HDD_CFG80211_ADD_STA,
13515 pAdapter->sessionId, params->listen_interval));
13516
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013517 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013518 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013519
13520 mask = params->sta_flags_mask;
13521
13522 set = params->sta_flags_set;
13523
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013524 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013525 MAC_ADDR_ARRAY(mac));
13526
13527 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13528 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13529 status =
13530 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13531 }
13532 }
13533#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013534 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013535 return status;
13536}
13537
13538/**
13539 * wlan_hdd_cfg80211_add_station() - add station
13540 * @wiphy: Pointer to wiphy
13541 * @mac: Pointer to station mac address
13542 * @pmksa: Pointer to add station parameter
13543 *
13544 * Return: 0 for success, non-zero for failure
13545 */
13546#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13547static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13548 struct net_device *dev,
13549 const uint8_t *mac,
13550 struct station_parameters *params)
13551#else
13552static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13553 struct net_device *dev, uint8_t *mac,
13554 struct station_parameters *params)
13555#endif
13556{
13557 int ret;
13558
13559 cds_ssr_protect(__func__);
13560 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13561 cds_ssr_unprotect(__func__);
13562
13563 return ret;
13564}
13565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013566/**
13567 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13568 * @wiphy: Pointer to wiphy
13569 * @dev: Pointer to network device
13570 * @pmksa: Pointer to set pmksa parameter
13571 *
13572 * Return: 0 for success, non-zero for failure
13573 */
13574static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13575 struct net_device *dev,
13576 struct cfg80211_pmksa *pmksa)
13577{
13578 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13579 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13580 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013581 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 int status;
13583 tPmkidCacheInfo pmk_id;
13584
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013585 ENTER();
13586
Anurag Chouhan6d760662016-02-20 16:05:43 +053013587 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013588 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013589 return -EINVAL;
13590 }
13591
13592 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013593 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013594 return -EINVAL;
13595 }
13596
13597 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013598 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013599 pmksa->bssid, pmksa->pmkid);
13600 return -EINVAL;
13601 }
13602
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013603 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013604 MAC_ADDR_ARRAY(pmksa->bssid));
13605
13606 status = wlan_hdd_validate_context(pHddCtx);
13607
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013608 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013609 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610
13611 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13612
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013613 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13614 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013615
13616 /* Add to the PMKSA ID Cache in CSR */
13617 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13618 &pmk_id, 1, false);
13619
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013620 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13622 pAdapter->sessionId, result));
13623
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013624 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013625 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626}
13627
13628/**
13629 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13630 * @wiphy: Pointer to wiphy
13631 * @dev: Pointer to network device
13632 * @pmksa: Pointer to set pmksa parameter
13633 *
13634 * Return: 0 for success, non-zero for failure
13635 */
13636static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13637 struct net_device *dev,
13638 struct cfg80211_pmksa *pmksa)
13639{
13640 int ret;
13641
13642 cds_ssr_protect(__func__);
13643 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13644 cds_ssr_unprotect(__func__);
13645
13646 return ret;
13647}
13648
13649/**
13650 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13651 * @wiphy: Pointer to wiphy
13652 * @dev: Pointer to network device
13653 * @pmksa: Pointer to pmksa parameter
13654 *
13655 * Return: 0 for success, non-zero for failure
13656 */
13657static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13658 struct net_device *dev,
13659 struct cfg80211_pmksa *pmksa)
13660{
13661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13662 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13663 tHalHandle halHandle;
13664 int status = 0;
13665
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013666 ENTER();
13667
Anurag Chouhan6d760662016-02-20 16:05:43 +053013668 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013669 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 return -EINVAL;
13671 }
13672
13673 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013674 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013675 return -EINVAL;
13676 }
13677
13678 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013679 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 return -EINVAL;
13681 }
13682
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013683 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 MAC_ADDR_ARRAY(pmksa->bssid));
13685
13686 status = wlan_hdd_validate_context(pHddCtx);
13687
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013688 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013689 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690
13691 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13692
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013693 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013694 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13695 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013697 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013698 sme_roam_del_pmkid_from_cache(halHandle,
13699 pAdapter->sessionId, pmksa->bssid,
13700 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013701 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 MAC_ADDR_ARRAY(pmksa->bssid));
13703 status = -EINVAL;
13704 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013705 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 return status;
13707}
13708
13709/**
13710 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13711 * @wiphy: Pointer to wiphy
13712 * @dev: Pointer to network device
13713 * @pmksa: Pointer to pmksa parameter
13714 *
13715 * Return: 0 for success, non-zero for failure
13716 */
13717static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13718 struct net_device *dev,
13719 struct cfg80211_pmksa *pmksa)
13720{
13721 int ret;
13722
13723 cds_ssr_protect(__func__);
13724 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13725 cds_ssr_unprotect(__func__);
13726
13727 return ret;
13728
13729}
13730
13731/**
13732 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13733 * @wiphy: Pointer to wiphy
13734 * @dev: Pointer to network device
13735 *
13736 * Return: 0 for success, non-zero for failure
13737 */
13738static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13739 struct net_device *dev)
13740{
13741 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13742 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13743 tHalHandle halHandle;
13744 int status = 0;
13745
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013746 ENTER();
13747
Anurag Chouhan6d760662016-02-20 16:05:43 +053013748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013749 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 return -EINVAL;
13751 }
13752
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013753 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013754
13755 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13756 status = wlan_hdd_validate_context(pHddCtx);
13757
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013758 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013759 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760
13761 /* Retrieve halHandle */
13762 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13763
13764 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013765 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13767 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013768 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 status = -EINVAL;
13770 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013771 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772 return status;
13773}
13774
13775/**
13776 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13777 * @wiphy: Pointer to wiphy
13778 * @dev: Pointer to network device
13779 *
13780 * Return: 0 for success, non-zero for failure
13781 */
13782static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13783 struct net_device *dev)
13784{
13785 int ret;
13786
13787 cds_ssr_protect(__func__);
13788 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13789 cds_ssr_unprotect(__func__);
13790
13791 return ret;
13792}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013794#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013795/**
13796 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13797 * @wiphy: Pointer to wiphy
13798 * @dev: Pointer to network device
13799 * @ftie: Pointer to fast transition ie parameter
13800 *
13801 * Return: 0 for success, non-zero for failure
13802 */
13803static int
13804__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13805 struct net_device *dev,
13806 struct cfg80211_update_ft_ies_params *ftie)
13807{
13808 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13809 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13810 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13811 int status;
13812
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013813 ENTER();
13814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013815 status = wlan_hdd_validate_context(hdd_ctx);
13816 if (status)
13817 return status;
13818
Anurag Chouhan6d760662016-02-20 16:05:43 +053013819 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013820 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013821 return -EINVAL;
13822 }
13823
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013824 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13826 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13827 /* Added for debug on reception of Re-assoc Req. */
13828 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013829 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013831 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013832 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013833 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835
13836 /* Pass the received FT IEs to SME */
13837 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13838 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013839 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 return 0;
13841}
13842
13843/**
13844 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13845 * @wiphy: Pointer to wiphy
13846 * @dev: Pointer to network device
13847 * @ftie: Pointer to fast transition ie parameter
13848 *
13849 * Return: 0 for success, non-zero for failure
13850 */
13851static int
13852wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13853 struct net_device *dev,
13854 struct cfg80211_update_ft_ies_params *ftie)
13855{
13856 int ret;
13857
13858 cds_ssr_protect(__func__);
13859 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13860 cds_ssr_unprotect(__func__);
13861
13862 return ret;
13863}
13864#endif
13865
13866#ifdef WLAN_FEATURE_GTK_OFFLOAD
13867/**
13868 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13869 * @callbackContext: Callback context
13870 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13871 *
13872 * Callback rountine called upon receiving response for get offload info
13873 *
13874 * Return: none
13875 */
13876void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13877 tpSirGtkOffloadGetInfoRspParams
13878 pGtkOffloadGetInfoRsp)
13879{
13880 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13881 uint8_t tempReplayCounter[8];
13882 hdd_station_ctx_t *pHddStaCtx;
13883
13884 ENTER();
13885
13886 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013887 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013888 return;
13889 }
13890
13891 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013892 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013893 return;
13894 }
13895
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013896 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013897 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013898 return;
13899 }
13900
13901 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13902 /* Update replay counter */
13903 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13904 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13905
13906 {
13907 /* changing from little to big endian since supplicant
13908 * works on big endian format
13909 */
13910 int i;
13911 uint8_t *p =
13912 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13913
13914 for (i = 0; i < 8; i++) {
13915 tempReplayCounter[7 - i] = (uint8_t) p[i];
13916 }
13917 }
13918
13919 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013920 cfg80211_gtk_rekey_notify(pAdapter->dev,
13921 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922 tempReplayCounter, GFP_KERNEL);
13923}
13924
13925/**
13926 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13927 * @wiphy: Pointer to wiphy
13928 * @dev: Pointer to network device
13929 * @data: Pointer to rekey data
13930 *
13931 * This function is used to offload GTK rekeying job to the firmware.
13932 *
13933 * Return: 0 for success, non-zero for failure
13934 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013935static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013936int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13937 struct net_device *dev,
13938 struct cfg80211_gtk_rekey_data *data)
13939{
13940 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13941 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13942 hdd_station_ctx_t *pHddStaCtx;
13943 tHalHandle hHal;
13944 int result;
13945 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013946 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013947
13948 ENTER();
13949
Anurag Chouhan6d760662016-02-20 16:05:43 +053013950 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013951 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013952 return -EINVAL;
13953 }
13954
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013955 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13957 pAdapter->sessionId, pAdapter->device_mode));
13958
13959 result = wlan_hdd_validate_context(pHddCtx);
13960
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013961 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013963
13964 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13965 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13966 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013967 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013968 return -EAGAIN;
13969 }
13970
13971 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13972 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
13973 NL80211_KCK_LEN);
13974 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
13975 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053013976 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013977 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978 {
13979 /* changing from big to little endian since driver
13980 * works on little endian format
13981 */
13982 uint8_t *p =
13983 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
13984 ullKeyReplayCounter;
13985 int i;
13986
13987 for (i = 0; i < 8; i++) {
13988 p[7 - i] = data->replay_ctr[i];
13989 }
13990 }
13991
13992 if (true == pHddCtx->hdd_wlan_suspended) {
13993 /* if wlan is suspended, enable GTK offload directly from here */
13994 memcpy(&hddGtkOffloadReqParams,
13995 &pHddStaCtx->gtkOffloadReqParams,
13996 sizeof(tSirGtkOffloadParams));
13997 status =
13998 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
13999 pAdapter->sessionId);
14000
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014001 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014002 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003 status);
14004 return -EINVAL;
14005 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014006 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014008 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014010 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 return result;
14012}
14013
14014/**
14015 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14016 * @wiphy: Pointer to wiphy
14017 * @dev: Pointer to network device
14018 * @data: Pointer to rekey data
14019 *
14020 * This function is used to offload GTK rekeying job to the firmware.
14021 *
14022 * Return: 0 for success, non-zero for failure
14023 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014024static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14026 struct net_device *dev,
14027 struct cfg80211_gtk_rekey_data *data)
14028{
14029 int ret;
14030
14031 cds_ssr_protect(__func__);
14032 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14033 cds_ssr_unprotect(__func__);
14034
14035 return ret;
14036}
14037#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14038
14039/**
14040 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14041 * @wiphy: Pointer to wiphy
14042 * @dev: Pointer to network device
14043 * @param: Pointer to access control parameter
14044 *
14045 * Return: 0 for success, non-zero for failure
14046 */
14047static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14048 struct net_device *dev,
14049 const struct cfg80211_acl_data *params)
14050{
14051 int i;
14052 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14053 hdd_hostapd_state_t *pHostapdState;
14054 tsap_Config_t *pConfig;
14055 v_CONTEXT_t p_cds_context = NULL;
14056 hdd_context_t *pHddCtx;
14057 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014058 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059
14060 ENTER();
14061
Anurag Chouhan6d760662016-02-20 16:05:43 +053014062 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014063 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014064 return -EINVAL;
14065 }
14066
14067 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014068 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 return -EINVAL;
14070 }
14071
14072 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14073 status = wlan_hdd_validate_context(pHddCtx);
14074
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014075 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077
14078 p_cds_context = pHddCtx->pcds_context;
14079 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14080
14081 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014082 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014083 return -EINVAL;
14084 }
14085
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014086 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087 params->n_acl_entries);
14088
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014089 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014090 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14091 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014092 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14094
14095 /* default value */
14096 pConfig->num_accept_mac = 0;
14097 pConfig->num_deny_mac = 0;
14098
14099 /**
14100 * access control policy
14101 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14102 * listed in hostapd.deny file.
14103 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14104 * listed in hostapd.accept file.
14105 */
14106 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14107 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14108 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14109 params->acl_policy) {
14110 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14111 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014112 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014113 params->acl_policy);
14114 return -ENOTSUPP;
14115 }
14116
14117 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14118 pConfig->num_accept_mac = params->n_acl_entries;
14119 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014120 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14121 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014122 MAC_ADDR_ARRAY(
14123 params->mac_addrs[i].addr));
14124
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014125 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014126 params->mac_addrs[i].addr,
14127 sizeof(qcmacaddr));
14128 }
14129 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14130 pConfig->num_deny_mac = params->n_acl_entries;
14131 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014132 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14133 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 MAC_ADDR_ARRAY(
14135 params->mac_addrs[i].addr));
14136
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014137 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138 params->mac_addrs[i].addr,
14139 sizeof(qcmacaddr));
14140 }
14141 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014142 qdf_status = wlansap_set_mac_acl(
14143 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014144 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014145 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 return -EINVAL;
14147 }
14148 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014149 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014150 hdd_device_mode_to_string(pAdapter->device_mode),
14151 pAdapter->device_mode);
14152 return -EINVAL;
14153 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014154 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155 return 0;
14156}
14157
14158/**
14159 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14160 * __wlan_hdd_cfg80211_set_mac_acl
14161 * @wiphy: pointer to wiphy structure
14162 * @dev: pointer to net_device
14163 * @params: pointer to cfg80211_acl_data
14164 *
14165 * Return; 0 on success, error number otherwise
14166 */
14167static int
14168wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14169 struct net_device *dev,
14170 const struct cfg80211_acl_data *params)
14171{
14172 int ret;
14173
14174 cds_ssr_protect(__func__);
14175 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14176 cds_ssr_unprotect(__func__);
14177
14178 return ret;
14179}
14180
14181#ifdef WLAN_NL80211_TESTMODE
14182#ifdef FEATURE_WLAN_LPHB
14183/**
14184 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14185 * @pHddCtx: Pointer to hdd context
14186 * @lphbInd: Pointer to low power heart beat indication parameter
14187 *
14188 * Return: none
14189 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014190static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14191 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014192{
14193 struct sk_buff *skb;
14194
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014195 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014197 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014198 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014199
14200 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014201 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014202 return;
14203 }
14204
14205 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14206 wiphy, sizeof(tSirLPHBInd),
14207 GFP_ATOMIC);
14208 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014209 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210 return;
14211 }
14212
14213 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014214 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 goto nla_put_failure;
14216 }
14217 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014218 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014219 goto nla_put_failure;
14220 }
14221 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014222 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014223 goto nla_put_failure;
14224 }
14225 cfg80211_testmode_event(skb, GFP_ATOMIC);
14226 return;
14227
14228nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014229 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014230 kfree_skb(skb);
14231
14232 return;
14233}
14234#endif /* FEATURE_WLAN_LPHB */
14235
14236/**
14237 * __wlan_hdd_cfg80211_testmode() - test mode
14238 * @wiphy: Pointer to wiphy
14239 * @data: Data pointer
14240 * @len: Data length
14241 *
14242 * Return: 0 for success, non-zero for failure
14243 */
14244static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14245 void *data, int len)
14246{
14247 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14248 int err;
14249 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14250
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014251 ENTER();
14252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014253 err = wlan_hdd_validate_context(pHddCtx);
14254 if (err)
14255 return err;
14256
14257 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14258 len, wlan_hdd_tm_policy);
14259 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014260 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 return err;
14262 }
14263
14264 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014265 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014266 return -EINVAL;
14267 }
14268
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014269 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014270 TRACE_CODE_HDD_CFG80211_TESTMODE,
14271 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014272 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14273#ifdef FEATURE_WLAN_LPHB
14274 /* Low Power Heartbeat configuration request */
14275 case WLAN_HDD_TM_CMD_WLAN_HB:
14276 {
14277 int buf_len;
14278 void *buf;
14279 tSirLPHBReq *hb_params = NULL;
14280 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014281 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282
14283 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014284 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014285 return -EINVAL;
14286 }
14287
14288 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14289 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14290
14291 hb_params_temp = (tSirLPHBReq *) buf;
14292 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14293 && (hb_params_temp->params.lphbTcpParamReq.
14294 timePeriodSec == 0))
14295 return -EINVAL;
14296
14297 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014298 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014300 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 return -ENOMEM;
14302 }
14303
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014304 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014305 smeStatus =
14306 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14307 hb_params,
14308 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014309 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014310 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014311 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312 }
14313 return 0;
14314 }
14315#endif /* FEATURE_WLAN_LPHB */
14316
14317#if defined(QCA_WIFI_FTM)
14318 case WLAN_HDD_TM_CMD_WLAN_FTM:
14319 {
14320 int buf_len;
14321 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014322 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014324 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 return -EINVAL;
14326 }
14327
14328 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14329 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14330
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014331 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014332
14333 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14334
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014335 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014336 err = -EBUSY;
14337 break;
14338 }
14339#endif
14340
14341 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014342 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14344 return -EOPNOTSUPP;
14345 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014346 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 return err;
14348}
14349
14350/**
14351 * wlan_hdd_cfg80211_testmode() - test mode
14352 * @wiphy: Pointer to wiphy
14353 * @dev: Pointer to network device
14354 * @data: Data pointer
14355 * @len: Data length
14356 *
14357 * Return: 0 for success, non-zero for failure
14358 */
14359static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14361 struct wireless_dev *wdev,
14362#endif
14363 void *data, int len)
14364{
14365 int ret;
14366
14367 cds_ssr_protect(__func__);
14368 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14369 cds_ssr_unprotect(__func__);
14370
14371 return ret;
14372}
14373
14374#if defined(QCA_WIFI_FTM)
14375/**
14376 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14377 * @buf: Pointer to buffer
14378 * @buf_len: Buffer length
14379 *
14380 * Return: none
14381 */
14382void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14383{
14384 struct sk_buff *skb;
14385 hdd_context_t *hdd_ctx;
14386
14387 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014388 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389 return;
14390 }
14391
Anurag Chouhan6d760662016-02-20 16:05:43 +053014392 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014394 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014395 return;
14396 }
14397
14398 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14399 buf_len, GFP_KERNEL);
14400 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014401 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014402 return;
14403 }
14404
14405 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14406 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14407 goto nla_put_failure;
14408
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014409 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014410
14411 cfg80211_testmode_event(skb, GFP_KERNEL);
14412 return;
14413
14414nla_put_failure:
14415 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014416 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014417}
14418#endif
14419#endif /* CONFIG_NL80211_TESTMODE */
14420
14421#ifdef QCA_HT_2040_COEX
14422/**
14423 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14424 * @wiphy: Pointer to wiphy
14425 * @dev: Pointer to network device
14426 * @chandef: Pointer to channel definition parameter
14427 *
14428 * Return: 0 for success, non-zero for failure
14429 */
14430static int
14431__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14432 struct net_device *dev,
14433 struct cfg80211_chan_def *chandef)
14434{
14435 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14436 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014437 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014438 tSmeConfigParams sme_config;
14439 bool cbModeChange;
14440
Anurag Chouhan6d760662016-02-20 16:05:43 +053014441 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014442 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443 return -EINVAL;
14444 }
14445
14446 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14447 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014448 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014451 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 sme_get_config_param(pHddCtx->hHal, &sme_config);
14453 switch (chandef->width) {
14454 case NL80211_CHAN_WIDTH_20:
14455 if (sme_config.csrConfig.channelBondingMode24GHz !=
14456 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14457 sme_config.csrConfig.channelBondingMode24GHz =
14458 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14459 sme_update_config(pHddCtx->hHal, &sme_config);
14460 cbModeChange = true;
14461 }
14462 break;
14463
14464 case NL80211_CHAN_WIDTH_40:
14465 if (sme_config.csrConfig.channelBondingMode24GHz ==
14466 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14467 if (NL80211_CHAN_HT40MINUS ==
14468 cfg80211_get_chandef_type(chandef))
14469 sme_config.csrConfig.channelBondingMode24GHz =
14470 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14471 else
14472 sme_config.csrConfig.channelBondingMode24GHz =
14473 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14474 sme_update_config(pHddCtx->hHal, &sme_config);
14475 cbModeChange = true;
14476 }
14477 break;
14478
14479 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014480 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 return -EINVAL;
14482 }
14483
14484 if (!cbModeChange)
14485 return 0;
14486
Krunal Sonib4326f22016-03-10 13:05:51 -080014487 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014488 return 0;
14489
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014490 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014491 sme_config.csrConfig.channelBondingMode24GHz);
14492
14493 /* Change SAP ht2040 mode */
14494 status = hdd_set_sap_ht2040_mode(pAdapter,
14495 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014496 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014497 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014498 return -EINVAL;
14499 }
14500
14501 return 0;
14502}
14503
14504/**
14505 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14506 * @wiphy: Pointer to wiphy
14507 * @dev: Pointer to network device
14508 * @chandef: Pointer to channel definition parameter
14509 *
14510 * Return: 0 for success, non-zero for failure
14511 */
14512static int
14513wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14514 struct net_device *dev,
14515 struct cfg80211_chan_def *chandef)
14516{
14517 int ret;
14518
14519 cds_ssr_protect(__func__);
14520 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14521 cds_ssr_unprotect(__func__);
14522
14523 return ret;
14524}
14525#endif
14526
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014527#ifdef CHANNEL_SWITCH_SUPPORTED
14528/**
14529 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14530 * channel in SAP/GO
14531 * @wiphy: wiphy pointer
14532 * @dev: dev pointer.
14533 * @csa_params: Change channel params
14534 *
14535 * This function is called to switch channel in SAP/GO
14536 *
14537 * Return: 0 if success else return non zero
14538 */
14539static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14540 struct net_device *dev,
14541 struct cfg80211_csa_settings *csa_params)
14542{
14543 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14544 hdd_context_t *hdd_ctx;
14545 uint8_t channel;
14546 uint16_t freq;
14547 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014548 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014549
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014550 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014551 csa_params->chandef.chan->center_freq);
14552
14553 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14554 ret = wlan_hdd_validate_context(hdd_ctx);
14555
14556 if (0 != ret)
14557 return ret;
14558
Krunal Sonib4326f22016-03-10 13:05:51 -080014559 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14560 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014561 return -ENOTSUPP;
14562
14563 freq = csa_params->chandef.chan->center_freq;
14564 channel = cds_freq_to_chan(freq);
14565
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014566 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14567
14568 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014569 return ret;
14570}
14571
14572/**
14573 * wlan_hdd_cfg80211_channel_switch()- function to switch
14574 * channel in SAP/GO
14575 * @wiphy: wiphy pointer
14576 * @dev: dev pointer.
14577 * @csa_params: Change channel params
14578 *
14579 * This function is called to switch channel in SAP/GO
14580 *
14581 * Return: 0 if success else return non zero
14582 */
14583static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14584 struct net_device *dev,
14585 struct cfg80211_csa_settings *csa_params)
14586{
14587 int ret;
14588
14589 cds_ssr_protect(__func__);
14590 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14591 cds_ssr_unprotect(__func__);
14592 return ret;
14593}
14594#endif
14595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014596/**
14597 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14598 * translation from NL to policy manager type
14599 * @type: Generic connection mode type defined in NL
14600 *
14601 *
14602 * This function provides the type translation
14603 *
14604 * Return: cds_con_mode enum
14605 */
14606enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14607 enum nl80211_iftype type)
14608{
14609 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14610 switch (type) {
14611 case NL80211_IFTYPE_STATION:
14612 mode = CDS_STA_MODE;
14613 break;
14614 case NL80211_IFTYPE_P2P_CLIENT:
14615 mode = CDS_P2P_CLIENT_MODE;
14616 break;
14617 case NL80211_IFTYPE_P2P_GO:
14618 mode = CDS_P2P_GO_MODE;
14619 break;
14620 case NL80211_IFTYPE_AP:
14621 mode = CDS_SAP_MODE;
14622 break;
14623 case NL80211_IFTYPE_ADHOC:
14624 mode = CDS_IBSS_MODE;
14625 break;
14626 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014627 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 type);
14629 }
14630 return mode;
14631}
14632
14633/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014634 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14635 * @wiphy: Handle to struct wiphy to get handle to module context.
14636 * @chandef: Contains information about the capture channel to be set.
14637 *
14638 * This interface is called if and only if monitor mode interface alone is
14639 * active.
14640 *
14641 * Return: 0 success or error code on failure.
14642 */
14643static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14644 struct cfg80211_chan_def *chandef)
14645{
14646 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14647 hdd_adapter_t *adapter;
14648 hdd_station_ctx_t *sta_ctx;
14649 struct hdd_mon_set_ch_info *ch_info;
14650 QDF_STATUS status;
14651 tHalHandle hal_hdl;
14652 struct qdf_mac_addr bssid;
14653 tCsrRoamProfile roam_profile;
14654 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014655 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014656 int ret;
14657 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14658
14659 ENTER();
14660
14661 ret = wlan_hdd_validate_context(hdd_ctx);
14662 if (ret)
14663 return ret;
14664
14665 hal_hdl = hdd_ctx->hHal;
14666
14667 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14668 if (!adapter)
14669 return -EIO;
14670
14671 hdd_info("%s: set monitor mode Channel %d and freq %d",
14672 adapter->dev->name, chan_num, chandef->chan->center_freq);
14673
14674 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14675 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014676 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14677 roam_profile.ChannelInfo.numOfChannels = 1;
14678 roam_profile.phyMode = ch_info->phy_mode;
14679 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014680 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014681
14682 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14683 QDF_MAC_ADDR_SIZE);
14684
14685 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014686 /*
14687 * CDS api expects secondary channel for calculating
14688 * the channel params
14689 */
14690 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14691 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14692 if (chan_num >= 1 && chan_num <= 5)
14693 sec_ch = chan_num + 4;
14694 else if (chan_num >= 6 && chan_num <= 13)
14695 sec_ch = chan_num - 4;
14696 }
14697 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014698 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14699 &roam_profile);
14700 if (status) {
14701 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14702 status);
14703 ret = qdf_status_to_os_return(status);
14704 return ret;
14705 }
14706 EXIT();
14707 return 0;
14708}
14709
14710/**
14711 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14712 * @wiphy: Handle to struct wiphy to get handle to module context.
14713 * @chandef: Contains information about the capture channel to be set.
14714 *
14715 * This interface is called if and only if monitor mode interface alone is
14716 * active.
14717 *
14718 * Return: 0 success or error code on failure.
14719 */
14720static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14721 struct cfg80211_chan_def *chandef)
14722{
14723 int ret;
14724
14725 cds_ssr_protect(__func__);
14726 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14727 cds_ssr_unprotect(__func__);
14728 return ret;
14729}
14730
14731/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732 * struct cfg80211_ops - cfg80211_ops
14733 *
14734 * @add_virtual_intf: Add virtual interface
14735 * @del_virtual_intf: Delete virtual interface
14736 * @change_virtual_intf: Change virtual interface
14737 * @change_station: Change station
14738 * @add_beacon: Add beacon in sap mode
14739 * @del_beacon: Delete beacon in sap mode
14740 * @set_beacon: Set beacon in sap mode
14741 * @start_ap: Start ap
14742 * @change_beacon: Change beacon
14743 * @stop_ap: Stop ap
14744 * @change_bss: Change bss
14745 * @add_key: Add key
14746 * @get_key: Get key
14747 * @del_key: Delete key
14748 * @set_default_key: Set default key
14749 * @set_channel: Set channel
14750 * @scan: Scan
14751 * @connect: Connect
14752 * @disconnect: Disconnect
14753 * @join_ibss = Join ibss
14754 * @leave_ibss = Leave ibss
14755 * @set_wiphy_params = Set wiphy params
14756 * @set_tx_power = Set tx power
14757 * @get_tx_power = get tx power
14758 * @remain_on_channel = Remain on channel
14759 * @cancel_remain_on_channel = Cancel remain on channel
14760 * @mgmt_tx = Tx management frame
14761 * @mgmt_tx_cancel_wait = Cancel management tx wait
14762 * @set_default_mgmt_key = Set default management key
14763 * @set_txq_params = Set tx queue parameters
14764 * @get_station = Get station
14765 * @set_power_mgmt = Set power management
14766 * @del_station = Delete station
14767 * @add_station = Add station
14768 * @set_pmksa = Set pmksa
14769 * @del_pmksa = Delete pmksa
14770 * @flush_pmksa = Flush pmksa
14771 * @update_ft_ies = Update FT IEs
14772 * @tdls_mgmt = Tdls management
14773 * @tdls_oper = Tdls operation
14774 * @set_rekey_data = Set rekey data
14775 * @sched_scan_start = Scheduled scan start
14776 * @sched_scan_stop = Scheduled scan stop
14777 * @resume = Resume wlan
14778 * @suspend = Suspend wlan
14779 * @set_mac_acl = Set mac acl
14780 * @testmode_cmd = Test mode command
14781 * @set_ap_chanwidth = Set AP channel bandwidth
14782 * @dump_survey = Dump survey
14783 * @key_mgmt_set_pmk = Set pmk key management
14784 */
14785static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14786 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14787 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14788 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14789 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014790 .start_ap = wlan_hdd_cfg80211_start_ap,
14791 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14792 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 .change_bss = wlan_hdd_cfg80211_change_bss,
14794 .add_key = wlan_hdd_cfg80211_add_key,
14795 .get_key = wlan_hdd_cfg80211_get_key,
14796 .del_key = wlan_hdd_cfg80211_del_key,
14797 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14798 .scan = wlan_hdd_cfg80211_scan,
14799 .connect = wlan_hdd_cfg80211_connect,
14800 .disconnect = wlan_hdd_cfg80211_disconnect,
14801 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14802 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14803 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14804 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14805 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14806 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14807 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14808 .mgmt_tx = wlan_hdd_mgmt_tx,
14809 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14810 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14811 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014812 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 .get_station = wlan_hdd_cfg80211_get_station,
14814 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14815 .del_station = wlan_hdd_cfg80211_del_station,
14816 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14818 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14819 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014820#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014821 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14822#endif
14823#ifdef FEATURE_WLAN_TDLS
14824 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14825 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14826#endif
14827#ifdef WLAN_FEATURE_GTK_OFFLOAD
14828 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14829#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14830#ifdef FEATURE_WLAN_SCAN_PNO
14831 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14832 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14833#endif /*FEATURE_WLAN_SCAN_PNO */
14834 .resume = wlan_hdd_cfg80211_resume_wlan,
14835 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14836 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14837#ifdef WLAN_NL80211_TESTMODE
14838 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14839#endif
14840#ifdef QCA_HT_2040_COEX
14841 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14842#endif
14843 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014844#ifdef CHANNEL_SWITCH_SUPPORTED
14845 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14846#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014847 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014848#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14849 defined(CFG80211_ABORT_SCAN)
14850 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14851#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852};