blob: 311114c8f5b8c954e33ae532484c6fb4639e207b [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 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
Paul Zhang3a210c52016-12-08 10:18:12 +080081#ifdef WLAN_UMAC_CONVERGENCE
82#include "wlan_cfg80211.h"
83#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084
85#ifdef FEATURE_WLAN_EXTSCAN
86#include "wlan_hdd_ext_scan.h"
87#endif
88
89#ifdef WLAN_FEATURE_LINK_LAYER_STATS
90#include "wlan_hdd_stats.h"
91#endif
92#include "cds_concurrency.h"
93#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800104
Leo Changfdb45c32016-10-28 11:09:23 -0700105#include <cdp_txrx_cmn.h>
106#include <cdp_txrx_misc.h>
107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
111 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
112
113/*
114 * Android CTS verifier needs atleast this much wait time (in msec)
115 */
116#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
117
118/*
119 * Refer @tCfgProtection structure for definition of the bit map.
120 * below value is obtained by setting the following bit-fields.
121 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
122 */
123#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
124
125#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700126 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127 .center_freq = (freq), \
128 .hw_value = (chan), \
129 .flags = (flag), \
130 .max_antenna_gain = 0, \
131 .max_power = 30, \
132}
133
134#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700135 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136 .center_freq = (freq), \
137 .hw_value = (chan), \
138 .flags = (flag), \
139 .max_antenna_gain = 0, \
140 .max_power = 30, \
141}
142
143#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
144 { \
145 .bitrate = rate, \
146 .hw_value = rate_id, \
147 .flags = flag, \
148 }
149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
151#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152
153#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154
Agrawal Ashish65634612016-08-18 13:24:32 +0530155#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
156 mode <= DFS_MODE_DEPRIORITIZE))
157#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
158 || (channel >= 36 && channel <= 184))
159
Peng Xu4d67c8f2015-10-16 16:02:26 -0700160#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530161#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163static const u32 hdd_cipher_suites[] = {
164 WLAN_CIPHER_SUITE_WEP40,
165 WLAN_CIPHER_SUITE_WEP104,
166 WLAN_CIPHER_SUITE_TKIP,
167#ifdef FEATURE_WLAN_ESE
168#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
169#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
170 WLAN_CIPHER_SUITE_BTK,
171 WLAN_CIPHER_SUITE_KRK,
172 WLAN_CIPHER_SUITE_CCMP,
173#else
174 WLAN_CIPHER_SUITE_CCMP,
175#endif
176#ifdef FEATURE_WLAN_WAPI
177 WLAN_CIPHER_SUITE_SMS4,
178#endif
179#ifdef WLAN_FEATURE_11W
180 WLAN_CIPHER_SUITE_AES_CMAC,
181#endif
182};
183
Abhishek Singhf512bf32016-05-04 16:47:46 +0530184static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 HDD2GHZCHAN(2412, 1, 0),
186 HDD2GHZCHAN(2417, 2, 0),
187 HDD2GHZCHAN(2422, 3, 0),
188 HDD2GHZCHAN(2427, 4, 0),
189 HDD2GHZCHAN(2432, 5, 0),
190 HDD2GHZCHAN(2437, 6, 0),
191 HDD2GHZCHAN(2442, 7, 0),
192 HDD2GHZCHAN(2447, 8, 0),
193 HDD2GHZCHAN(2452, 9, 0),
194 HDD2GHZCHAN(2457, 10, 0),
195 HDD2GHZCHAN(2462, 11, 0),
196 HDD2GHZCHAN(2467, 12, 0),
197 HDD2GHZCHAN(2472, 13, 0),
198 HDD2GHZCHAN(2484, 14, 0),
199};
200
Abhishek Singhf512bf32016-05-04 16:47:46 +0530201static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800202 HDD5GHZCHAN(5180, 36, 0),
203 HDD5GHZCHAN(5200, 40, 0),
204 HDD5GHZCHAN(5220, 44, 0),
205 HDD5GHZCHAN(5240, 48, 0),
206 HDD5GHZCHAN(5260, 52, 0),
207 HDD5GHZCHAN(5280, 56, 0),
208 HDD5GHZCHAN(5300, 60, 0),
209 HDD5GHZCHAN(5320, 64, 0),
210 HDD5GHZCHAN(5500, 100, 0),
211 HDD5GHZCHAN(5520, 104, 0),
212 HDD5GHZCHAN(5540, 108, 0),
213 HDD5GHZCHAN(5560, 112, 0),
214 HDD5GHZCHAN(5580, 116, 0),
215 HDD5GHZCHAN(5600, 120, 0),
216 HDD5GHZCHAN(5620, 124, 0),
217 HDD5GHZCHAN(5640, 128, 0),
218 HDD5GHZCHAN(5660, 132, 0),
219 HDD5GHZCHAN(5680, 136, 0),
220 HDD5GHZCHAN(5700, 140, 0),
221 HDD5GHZCHAN(5720, 144, 0),
222 HDD5GHZCHAN(5745, 149, 0),
223 HDD5GHZCHAN(5765, 153, 0),
224 HDD5GHZCHAN(5785, 157, 0),
225 HDD5GHZCHAN(5805, 161, 0),
226 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227 HDD5GHZCHAN(5852, 170, 0),
228 HDD5GHZCHAN(5855, 171, 0),
229 HDD5GHZCHAN(5860, 172, 0),
230 HDD5GHZCHAN(5865, 173, 0),
231 HDD5GHZCHAN(5870, 174, 0),
232 HDD5GHZCHAN(5875, 175, 0),
233 HDD5GHZCHAN(5880, 176, 0),
234 HDD5GHZCHAN(5885, 177, 0),
235 HDD5GHZCHAN(5890, 178, 0),
236 HDD5GHZCHAN(5895, 179, 0),
237 HDD5GHZCHAN(5900, 180, 0),
238 HDD5GHZCHAN(5905, 181, 0),
239 HDD5GHZCHAN(5910, 182, 0),
240 HDD5GHZCHAN(5915, 183, 0),
241 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800242};
243
244static struct ieee80211_rate g_mode_rates[] = {
245 HDD_G_MODE_RATETAB(10, 0x1, 0),
246 HDD_G_MODE_RATETAB(20, 0x2, 0),
247 HDD_G_MODE_RATETAB(55, 0x4, 0),
248 HDD_G_MODE_RATETAB(110, 0x8, 0),
249 HDD_G_MODE_RATETAB(60, 0x10, 0),
250 HDD_G_MODE_RATETAB(90, 0x20, 0),
251 HDD_G_MODE_RATETAB(120, 0x40, 0),
252 HDD_G_MODE_RATETAB(180, 0x80, 0),
253 HDD_G_MODE_RATETAB(240, 0x100, 0),
254 HDD_G_MODE_RATETAB(360, 0x200, 0),
255 HDD_G_MODE_RATETAB(480, 0x400, 0),
256 HDD_G_MODE_RATETAB(540, 0x800, 0),
257};
258
259static struct ieee80211_rate a_mode_rates[] = {
260 HDD_G_MODE_RATETAB(60, 0x10, 0),
261 HDD_G_MODE_RATETAB(90, 0x20, 0),
262 HDD_G_MODE_RATETAB(120, 0x40, 0),
263 HDD_G_MODE_RATETAB(180, 0x80, 0),
264 HDD_G_MODE_RATETAB(240, 0x100, 0),
265 HDD_G_MODE_RATETAB(360, 0x200, 0),
266 HDD_G_MODE_RATETAB(480, 0x400, 0),
267 HDD_G_MODE_RATETAB(540, 0x800, 0),
268};
269
270static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530271 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800272 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700273 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800274 .bitrates = g_mode_rates,
275 .n_bitrates = g_mode_rates_size,
276 .ht_cap.ht_supported = 1,
277 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
278 | IEEE80211_HT_CAP_GRN_FLD
279 | IEEE80211_HT_CAP_DSSSCCK40
280 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
281 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
282 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
283 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
284 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
285 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
286 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
287};
288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530290 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700292 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 .bitrates = a_mode_rates,
294 .n_bitrates = a_mode_rates_size,
295 .ht_cap.ht_supported = 1,
296 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
297 | IEEE80211_HT_CAP_GRN_FLD
298 | IEEE80211_HT_CAP_DSSSCCK40
299 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
300 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
301 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
302 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
303 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
304 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
305 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
306 .vht_cap.vht_supported = 1,
307};
308
309/* This structure contain information what kind of frame are expected in
310 TX/RX direction for each kind of interface */
311static const struct ieee80211_txrx_stypes
312 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
313 [NL80211_IFTYPE_STATION] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ACTION) |
316 BIT(SIR_MAC_MGMT_PROBE_REQ),
317 },
318 [NL80211_IFTYPE_AP] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ) |
323 BIT(SIR_MAC_MGMT_DISASSOC) |
324 BIT(SIR_MAC_MGMT_AUTH) |
325 BIT(SIR_MAC_MGMT_DEAUTH) |
326 BIT(SIR_MAC_MGMT_ACTION),
327 },
328 [NL80211_IFTYPE_ADHOC] = {
329 .tx = 0xffff,
330 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ) |
333 BIT(SIR_MAC_MGMT_DISASSOC) |
334 BIT(SIR_MAC_MGMT_AUTH) |
335 BIT(SIR_MAC_MGMT_DEAUTH) |
336 BIT(SIR_MAC_MGMT_ACTION),
337 },
338 [NL80211_IFTYPE_P2P_CLIENT] = {
339 .tx = 0xffff,
340 .rx = BIT(SIR_MAC_MGMT_ACTION) |
341 BIT(SIR_MAC_MGMT_PROBE_REQ),
342 },
343 [NL80211_IFTYPE_P2P_GO] = {
344 /* This is also same as for SoftAP */
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
347 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
348 BIT(SIR_MAC_MGMT_PROBE_REQ) |
349 BIT(SIR_MAC_MGMT_DISASSOC) |
350 BIT(SIR_MAC_MGMT_AUTH) |
351 BIT(SIR_MAC_MGMT_DEAUTH) |
352 BIT(SIR_MAC_MGMT_ACTION),
353 },
354};
355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800356/* Interface limits and combinations registered by the driver */
357
358/* STA ( + STA ) combination */
359static const struct ieee80211_iface_limit
360 wlan_hdd_sta_iface_limit[] = {
361 {
362 .max = 3, /* p2p0 is a STA as well */
363 .types = BIT(NL80211_IFTYPE_STATION),
364 },
365};
366
367/* ADHOC (IBSS) limit */
368static const struct ieee80211_iface_limit
369 wlan_hdd_adhoc_iface_limit[] = {
370 {
371 .max = 1,
372 .types = BIT(NL80211_IFTYPE_STATION),
373 },
374 {
375 .max = 1,
376 .types = BIT(NL80211_IFTYPE_ADHOC),
377 },
378};
379
380/* AP ( + AP ) combination */
381static const struct ieee80211_iface_limit
382 wlan_hdd_ap_iface_limit[] = {
383 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530384 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 .types = BIT(NL80211_IFTYPE_AP),
386 },
387};
388
389/* P2P limit */
390static const struct ieee80211_iface_limit
391 wlan_hdd_p2p_iface_limit[] = {
392 {
393 .max = 1,
394 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396 {
397 .max = 1,
398 .types = BIT(NL80211_IFTYPE_P2P_GO),
399 },
400};
401
402static const struct ieee80211_iface_limit
403 wlan_hdd_sta_ap_iface_limit[] = {
404 {
405 /* We need 1 extra STA interface for OBSS scan when SAP starts
406 * with HT40 in STA+SAP concurrency mode
407 */
408 .max = (1 + SAP_MAX_OBSS_STA_CNT),
409 .types = BIT(NL80211_IFTYPE_STATION),
410 },
411 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530412 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 .types = BIT(NL80211_IFTYPE_AP),
414 },
415};
416
417/* STA + P2P combination */
418static const struct ieee80211_iface_limit
419 wlan_hdd_sta_p2p_iface_limit[] = {
420 {
421 /* One reserved for dedicated P2PDEV usage */
422 .max = 2,
423 .types = BIT(NL80211_IFTYPE_STATION)
424 },
425 {
426 /* Support for two identical (GO + GO or CLI + CLI)
427 * or dissimilar (GO + CLI) P2P interfaces
428 */
429 .max = 2,
430 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
431 },
432};
433
434/* STA + AP + P2PGO combination */
435static const struct ieee80211_iface_limit
436wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
437 /* Support for AP+P2PGO interfaces */
438 {
439 .max = 2,
440 .types = BIT(NL80211_IFTYPE_STATION)
441 },
442 {
443 .max = 1,
444 .types = BIT(NL80211_IFTYPE_P2P_GO)
445 },
446 {
447 .max = 1,
448 .types = BIT(NL80211_IFTYPE_AP)
449 }
450};
451
452/* SAP + P2P combination */
453static const struct ieee80211_iface_limit
454wlan_hdd_sap_p2p_iface_limit[] = {
455 {
456 /* 1 dedicated for p2p0 which is a STA type */
457 .max = 1,
458 .types = BIT(NL80211_IFTYPE_STATION)
459 },
460 {
461 /* The p2p interface in SAP+P2P can be GO/CLI.
462 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
463 */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
466 },
467 {
468 /* SAP+GO to support only one SAP interface */
469 .max = 1,
470 .types = BIT(NL80211_IFTYPE_AP)
471 }
472};
473
474/* P2P + P2P combination */
475static const struct ieee80211_iface_limit
476wlan_hdd_p2p_p2p_iface_limit[] = {
477 {
478 /* 1 dedicated for p2p0 which is a STA type */
479 .max = 1,
480 .types = BIT(NL80211_IFTYPE_STATION)
481 },
482 {
483 /* The p2p interface in P2P+P2P can be GO/CLI.
484 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
485 */
486 .max = 2,
487 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
488 },
489};
490
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700491static const struct ieee80211_iface_limit
492 wlan_hdd_mon_iface_limit[] = {
493 {
494 .max = 3, /* Monitor interface */
495 .types = BIT(NL80211_IFTYPE_MONITOR),
496 },
497};
498
499static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 wlan_hdd_iface_combination[] = {
501 /* STA */
502 {
503 .limits = wlan_hdd_sta_iface_limit,
504 .num_different_channels = 2,
505 .max_interfaces = 3,
506 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
507 },
508 /* ADHOC */
509 {
510 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700511 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512 .max_interfaces = 2,
513 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
514 },
515 /* AP */
516 {
517 .limits = wlan_hdd_ap_iface_limit,
518 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530519 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
521 },
522 /* P2P */
523 {
524 .limits = wlan_hdd_p2p_iface_limit,
525 .num_different_channels = 2,
526 .max_interfaces = 2,
527 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
528 },
529 /* STA + AP */
530 {
531 .limits = wlan_hdd_sta_ap_iface_limit,
532 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530533 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
535 .beacon_int_infra_match = true,
536 },
537 /* STA + P2P */
538 {
539 .limits = wlan_hdd_sta_p2p_iface_limit,
540 .num_different_channels = 2,
541 /* one interface reserved for P2PDEV dedicated usage */
542 .max_interfaces = 4,
543 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
544 .beacon_int_infra_match = true,
545 },
546 /* STA + P2P GO + SAP */
547 {
548 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
549 /* we can allow 3 channels for three different persona
550 * but due to firmware limitation, allow max 2 concrnt channels.
551 */
552 .num_different_channels = 2,
553 /* one interface reserved for P2PDEV dedicated usage */
554 .max_interfaces = 4,
555 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
556 .beacon_int_infra_match = true,
557 },
558 /* SAP + P2P */
559 {
560 .limits = wlan_hdd_sap_p2p_iface_limit,
561 .num_different_channels = 2,
562 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
563 .max_interfaces = 3,
564 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
565 .beacon_int_infra_match = true,
566 },
567 /* P2P + P2P */
568 {
569 .limits = wlan_hdd_p2p_p2p_iface_limit,
570 .num_different_channels = 2,
571 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
572 .max_interfaces = 3,
573 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
574 .beacon_int_infra_match = true,
575 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530576 /* Monitor */
577 {
578 .limits = wlan_hdd_mon_iface_limit,
579 .max_interfaces = 3,
580 .num_different_channels = 2,
581 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
582 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584
585static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530586struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800587
588#ifdef WLAN_NL80211_TESTMODE
589enum wlan_hdd_tm_attr {
590 WLAN_HDD_TM_ATTR_INVALID = 0,
591 WLAN_HDD_TM_ATTR_CMD = 1,
592 WLAN_HDD_TM_ATTR_DATA = 2,
593 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
594 WLAN_HDD_TM_ATTR_TYPE = 4,
595 /* keep last */
596 WLAN_HDD_TM_ATTR_AFTER_LAST,
597 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
598};
599
600enum wlan_hdd_tm_cmd {
601 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
602 WLAN_HDD_TM_CMD_WLAN_HB = 1,
603};
604
605#define WLAN_HDD_TM_DATA_MAX_LEN 5000
606
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530607enum wlan_hdd_vendor_ie_access_policy {
608 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
609 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
610};
611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
613 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
614 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
615 .len = WLAN_HDD_TM_DATA_MAX_LEN},
616};
617#endif /* WLAN_NL80211_TESTMODE */
618
619#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
620static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
621 .flags = WIPHY_WOWLAN_MAGIC_PKT,
622 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
623 .pattern_min_len = 1,
624 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
625};
626#endif
627
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530629 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
630 * @flags: Pointer to the flags to Add channel switch flag.
631 *
632 * This Function adds Channel Switch support flag, if channel switch is
633 * supported by kernel.
634 * Return: void.
635 */
636#ifdef CHANNEL_SWITCH_SUPPORTED
637static inline void hdd_add_channel_switch_support(uint32_t *flags)
638{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800639 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530640 return;
641}
642#else
643static inline void hdd_add_channel_switch_support(uint32_t *flags)
644{
645 return;
646}
647#endif
648
Manikandan Mohan22b83722015-12-15 15:03:23 -0800649#ifdef FEATURE_WLAN_TDLS
650
651/* TDLS capabilities params */
652#define PARAM_MAX_TDLS_SESSION \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
654#define PARAM_TDLS_FEATURE_SUPPORT \
655 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
656
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530657/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
659 * @wiphy: WIPHY structure pointer
660 * @wdev: Wireless device structure pointer
661 * @data: Pointer to the data received
662 * @data_len: Length of the data received
663 *
664 * This function provides TDLS capabilities
665 *
666 * Return: 0 on success and errno on failure
667 */
668static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
669 struct wireless_dev *wdev,
670 const void *data,
671 int data_len)
672{
673 int status;
674 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
675 struct sk_buff *skb;
676 uint32_t set = 0;
677
Jeff Johnson1f61b612016-02-12 16:28:33 -0800678 ENTER_DEV(wdev->netdev);
679
Anurag Chouhan6d760662016-02-20 16:05:43 +0530680 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681 hdd_err("Command not allowed in FTM mode");
682 return -EPERM;
683 }
684
685 status = wlan_hdd_validate_context(hdd_ctx);
686 if (status)
687 return status;
688
689 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
690 NLMSG_HDRLEN);
691 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 goto fail;
694 }
695
696 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700697 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
699 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700700 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800701 goto fail;
702 }
703 } else {
704 set = set | WIFI_TDLS_SUPPORT;
705 set = set | (hdd_ctx->config->fTDLSExternalControl ?
706 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
707 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
708 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
711 hdd_ctx->max_num_tdls_sta) ||
712 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
713 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700714 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 goto fail;
716 }
717 }
718 return cfg80211_vendor_cmd_reply(skb);
719fail:
720 if (skb)
721 kfree_skb(skb);
722 return -EINVAL;
723}
724
725/**
726 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
727 * @wiphy: WIPHY structure pointer
728 * @wdev: Wireless device structure pointer
729 * @data: Pointer to the data received
730 * @data_len: Length of the data received
731 *
732 * This function provides TDLS capabilities
733 *
734 * Return: 0 on success and errno on failure
735 */
736static int
737wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
738 struct wireless_dev *wdev,
739 const void *data,
740 int data_len)
741{
742 int ret;
743
744 cds_ssr_protect(__func__);
745 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
746 data, data_len);
747 cds_ssr_unprotect(__func__);
748
749 return ret;
750}
751#endif
752
753#ifdef QCA_HT_2040_COEX
754static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
755#endif
756
757#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
758/*
759 * FUNCTION: wlan_hdd_send_avoid_freq_event
760 * This is called when wlan driver needs to send vendor specific
761 * avoid frequency range event to userspace
762 */
763int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
764 tHddAvoidFreqList *pAvoidFreqList)
765{
766 struct sk_buff *vendor_event;
767
768 ENTER();
769
770 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700776 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 return -EINVAL;
778 }
779
780 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
781 NULL,
782 sizeof(tHddAvoidFreqList),
783 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
784 GFP_KERNEL);
785 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700786 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 return -EINVAL;
788 }
789
790 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
791 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
792
793 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
794
795 EXIT();
796 return 0;
797}
798#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
799
800/* vendor specific events */
801static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
802#ifdef FEATURE_WLAN_CH_AVOID
803 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
804 .vendor_id =
805 QCA_NL80211_VENDOR_ID,
806 .subcmd =
807 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
808 },
809#endif /* FEATURE_WLAN_CH_AVOID */
810
811#ifdef WLAN_FEATURE_NAN
812 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
813 .vendor_id =
814 QCA_NL80211_VENDOR_ID,
815 .subcmd =
816 QCA_NL80211_VENDOR_SUBCMD_NAN
817 },
818#endif
819
820#ifdef WLAN_FEATURE_STATS_EXT
821 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
822 .vendor_id =
823 QCA_NL80211_VENDOR_ID,
824 .subcmd =
825 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
826 },
827#endif /* WLAN_FEATURE_STATS_EXT */
828#ifdef FEATURE_WLAN_EXTSCAN
829 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
830 .vendor_id =
831 QCA_NL80211_VENDOR_ID,
832 .subcmd =
833 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
834 },
835 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
836 .vendor_id =
837 QCA_NL80211_VENDOR_ID,
838 .subcmd =
839 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
840 },
841 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
842 .
843 vendor_id
844 =
845 QCA_NL80211_VENDOR_ID,
846 .subcmd =
847 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
848 },
849 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
850 .
851 vendor_id
852 =
853 QCA_NL80211_VENDOR_ID,
854 .
855 subcmd =
856 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
857 },
858 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
859 .
860 vendor_id
861 =
862 QCA_NL80211_VENDOR_ID,
863 .
864 subcmd
865 =
866 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
867 },
868 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
869 .
870 vendor_id
871 =
872 QCA_NL80211_VENDOR_ID,
873 .subcmd =
874 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
875 },
876 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
877 .vendor_id =
878 QCA_NL80211_VENDOR_ID,
879 .subcmd =
880 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
881 },
882 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
883 .
884 vendor_id
885 =
886 QCA_NL80211_VENDOR_ID,
887 .subcmd =
888 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
889 },
890 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
891 .
892 vendor_id
893 =
894 QCA_NL80211_VENDOR_ID,
895 .subcmd =
896 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
897 },
898 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
899 .
900 vendor_id
901 =
902 QCA_NL80211_VENDOR_ID,
903 .
904 subcmd
905 =
906 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
907 },
908 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
909 .
910 vendor_id
911 =
912 QCA_NL80211_VENDOR_ID,
913 .
914 subcmd =
915 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
916 },
917 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
918 .
919 vendor_id
920 =
921 QCA_NL80211_VENDOR_ID,
922 .
923 subcmd
924 =
925 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
926 },
927 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
928 .
929 vendor_id
930 =
931 QCA_NL80211_VENDOR_ID,
932 .
933 subcmd
934 =
935 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
936 },
937 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
938 .vendor_id = QCA_NL80211_VENDOR_ID,
939 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
940 },
941 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
942 .vendor_id = QCA_NL80211_VENDOR_ID,
943 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
944 },
945#endif /* FEATURE_WLAN_EXTSCAN */
946
947#ifdef WLAN_FEATURE_LINK_LAYER_STATS
948 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
949 .vendor_id =
950 QCA_NL80211_VENDOR_ID,
951 .subcmd =
952 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
953 },
954 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
955 .vendor_id =
956 QCA_NL80211_VENDOR_ID,
957 .subcmd =
958 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
959 },
960 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
961 .vendor_id =
962 QCA_NL80211_VENDOR_ID,
963 .subcmd =
964 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
965 },
966 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
967 .vendor_id =
968 QCA_NL80211_VENDOR_ID,
969 .subcmd =
970 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
971 },
972 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
973 .vendor_id =
974 QCA_NL80211_VENDOR_ID,
975 .subcmd =
976 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
977 },
978 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
979 .vendor_id =
980 QCA_NL80211_VENDOR_ID,
981 .subcmd =
982 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
983 },
984#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
985 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
986 .vendor_id =
987 QCA_NL80211_VENDOR_ID,
988 .subcmd =
989 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
990 },
991 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
992 .vendor_id = QCA_NL80211_VENDOR_ID,
993 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
994 },
995#ifdef WLAN_FEATURE_ROAM_OFFLOAD
996 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
997 .vendor_id =
998 QCA_NL80211_VENDOR_ID,
999 .subcmd =
1000 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1001 },
1002#endif
1003 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1004 .vendor_id =
1005 QCA_NL80211_VENDOR_ID,
1006 .subcmd =
1007 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1008 },
1009 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1010 .vendor_id =
1011 QCA_NL80211_VENDOR_ID,
1012 .subcmd =
1013 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1014 },
1015 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1016 .vendor_id =
1017 QCA_NL80211_VENDOR_ID,
1018 .subcmd =
1019 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1020 },
1021 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1022 .vendor_id =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1026 },
1027 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1028 .vendor_id =
1029 QCA_NL80211_VENDOR_ID,
1030 .subcmd =
1031 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1032 },
1033#ifdef FEATURE_WLAN_EXTSCAN
1034 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1035 .vendor_id = QCA_NL80211_VENDOR_ID,
1036 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1037 },
1038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1043 .vendor_id = QCA_NL80211_VENDOR_ID,
1044 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1049 },
1050 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1053 },
1054#endif /* FEATURE_WLAN_EXTSCAN */
1055 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1058 },
1059#ifdef WLAN_FEATURE_MEMDUMP
1060 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1063 },
1064#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001065#ifdef WLAN_FEATURE_TSF
1066 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1069 },
1070#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1072 .vendor_id = QCA_NL80211_VENDOR_ID,
1073 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1074 },
1075 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1078 },
1079 /* OCB events */
1080 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1083 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001084#ifdef FEATURE_LFR_SUBNET_DETECTION
1085 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1086 .vendor_id = QCA_NL80211_VENDOR_ID,
1087 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1088 },
1089#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001090
1091#ifdef WLAN_FEATURE_NAN_DATAPATH
1092 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1093 .vendor_id = QCA_NL80211_VENDOR_ID,
1094 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1095 },
1096#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001097
1098 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1099 .vendor_id = QCA_NL80211_VENDOR_ID,
1100 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1101 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301102 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1105 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001106#ifdef WLAN_UMAC_CONVERGENCE
1107 COMMON_VENDOR_EVENTS
1108#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109};
1110
1111/**
1112 * __is_driver_dfs_capable() - get driver DFS capability
1113 * @wiphy: pointer to wireless wiphy structure.
1114 * @wdev: pointer to wireless_dev structure.
1115 * @data: Pointer to the data to be passed via vendor interface
1116 * @data_len:Length of the data to be passed
1117 *
1118 * This function is called by userspace to indicate whether or not
1119 * the driver supports DFS offload.
1120 *
1121 * Return: 0 on success, negative errno on failure
1122 */
1123static int __is_driver_dfs_capable(struct wiphy *wiphy,
1124 struct wireless_dev *wdev,
1125 const void *data,
1126 int data_len)
1127{
1128 u32 dfs_capability = 0;
1129 struct sk_buff *temp_skbuff;
1130 int ret_val;
1131 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1132
Jeff Johnson1f61b612016-02-12 16:28:33 -08001133 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134
1135 ret_val = wlan_hdd_validate_context(hdd_ctx);
1136 if (ret_val)
1137 return ret_val;
1138
Anurag Chouhan6d760662016-02-20 16:05:43 +05301139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 hdd_err("Command not allowed in FTM mode");
1141 return -EPERM;
1142 }
1143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145
1146 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1147 NLMSG_HDRLEN);
1148
1149 if (temp_skbuff != NULL) {
1150 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1151 dfs_capability);
1152 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001153 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 kfree_skb(temp_skbuff);
1155
1156 return ret_val;
1157 }
1158
1159 return cfg80211_vendor_cmd_reply(temp_skbuff);
1160 }
1161
Jeff Johnson020db452016-06-29 14:37:26 -07001162 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163 return -ENOMEM;
1164}
1165
1166/**
1167 * is_driver_dfs_capable() - get driver DFS capability
1168 * @wiphy: pointer to wireless wiphy structure.
1169 * @wdev: pointer to wireless_dev structure.
1170 * @data: Pointer to the data to be passed via vendor interface
1171 * @data_len:Length of the data to be passed
1172 *
1173 * This function is called by userspace to indicate whether or not
1174 * the driver supports DFS offload. This is an SSR-protected
1175 * wrapper function.
1176 *
1177 * Return: 0 on success, negative errno on failure
1178 */
1179static int is_driver_dfs_capable(struct wiphy *wiphy,
1180 struct wireless_dev *wdev,
1181 const void *data,
1182 int data_len)
1183{
1184 int ret;
1185
1186 cds_ssr_protect(__func__);
1187 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1188 cds_ssr_unprotect(__func__);
1189
1190 return ret;
1191}
1192
1193/**
1194 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1195 *
1196 * @adapter: SAP adapter pointer
1197 *
1198 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1199 * radio. So in case of DFS MCC scenario override current SAP given config
1200 * to follow concurrent SAP DFS config
1201 *
1202 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1203 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1205{
1206 hdd_adapter_t *con_sap_adapter;
1207 tsap_Config_t *sap_config, *con_sap_config;
1208 int con_ch;
1209
1210 /*
1211 * Check if AP+AP case, once primary AP chooses a DFS
1212 * channel secondary AP should always follow primary APs channel
1213 */
1214 if (!cds_concurrent_beaconing_sessions_running())
1215 return 0;
1216
1217 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1218 if (!con_sap_adapter)
1219 return 0;
1220
1221 sap_config = &adapter->sessionCtx.ap.sapConfig;
1222 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1223 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1224
1225 if (!CDS_IS_DFS_CH(con_ch))
1226 return 0;
1227
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel = con_ch;
1232
1233 if (con_sap_config->acs_cfg.acs_mode == true) {
1234 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1235 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001236 hdd_err("Primary AP channel config error");
1237 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 con_ch, con_sap_config->acs_cfg.pri_ch,
1239 con_sap_config->acs_cfg.ht_sec_ch);
1240 return -EINVAL;
1241 }
1242 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1243 * MCC restriction. So free ch list allocated in do_acs
1244 * func for Sec AP and realloc for Pri AP ch list size
1245 */
1246 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301247 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250 &con_sap_config->acs_cfg,
1251 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 sizeof(uint8_t) *
1254 con_sap_config->acs_cfg.ch_list_count);
1255 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001256 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 return -ENOMEM;
1258 }
1259
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301260 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 con_sap_config->acs_cfg.ch_list,
1262 con_sap_config->acs_cfg.ch_list_count);
1263
1264 } else {
1265 sap_config->acs_cfg.pri_ch = con_ch;
1266 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1267 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1268 }
1269
1270 return con_ch;
1271}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272
1273/**
1274 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1275 * @sap_cfg: pointer to SAP config struct
1276 *
1277 * This function sets the default ACS start and end channel for the given band
1278 * and also parses the given ACS channel list.
1279 *
1280 * Return: None
1281 */
1282
1283static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1284 bool vht_enabled)
1285{
1286 int i;
1287 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
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_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001297 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1298 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001301 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1302 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 }
1304
1305 if (ht_enabled)
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1307
1308 if (vht_enabled)
1309 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1310
1311
1312 /* Parse ACS Chan list from hostapd */
1313 if (!sap_cfg->acs_cfg.ch_list)
1314 return;
1315
1316 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1317 sap_cfg->acs_cfg.end_ch =
1318 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1319 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301320 /* avoid channel as start channel */
1321 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1322 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1324 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1325 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1326 }
1327}
1328
1329
1330static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1331
1332/**
1333 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1334 * @adapter: pointer to SAP adapter struct
1335 *
1336 * This function starts the ACS procedure if there are no
1337 * constraints like MBSSID DFS restrictions.
1338 *
1339 * Return: Status of ACS Start procedure
1340 */
1341
1342static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1343{
1344
1345 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1346 tsap_Config_t *sap_config;
1347 tpWLAN_SAPEventCB acs_event_callback;
1348 int status;
1349
1350 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301351 if (hdd_ctx->acs_policy.acs_channel)
1352 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1353 else
1354 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355
1356 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1357 if (status < 0) {
1358 return status;
1359 } else {
1360 if (status > 0) {
1361 /*notify hostapd about channel override */
1362 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1363 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1364 return 0;
1365 }
1366 }
1367 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1368 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 return -EINVAL;
1371 }
1372
1373 acs_event_callback = hdd_hostapd_sap_event_cb;
1374
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301375 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301376 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001377 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 acs_event_callback, sap_config, adapter->dev);
1381
1382
1383 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001384 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 return -EINVAL;
1386 }
1387 sap_config->acs_cfg.acs_mode = true;
1388 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1389
1390 return 0;
1391}
1392
1393/**
1394 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1395 * @wiphy: Linux wiphy struct pointer
1396 * @wdev: Linux wireless device struct pointer
1397 * @data: ACS information from hostapd
1398 * @data_len: ACS information length
1399 *
1400 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1401 * and starts ACS procedure.
1402 *
1403 * Return: ACS procedure start status
1404 */
1405
1406static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1407 struct wireless_dev *wdev,
1408 const void *data, int data_len)
1409{
1410 struct net_device *ndev = wdev->netdev;
1411 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1412 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1413 tsap_Config_t *sap_config;
1414 struct sk_buff *temp_skbuff;
1415 int status = -EINVAL, i = 0;
1416 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1417 bool ht_enabled, ht40_enabled, vht_enabled;
1418 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301419 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420
1421 /* ***Note*** Donot set SME config related to ACS operation here because
1422 * ACS operation is not synchronouse and ACS for Second AP may come when
1423 * ACS operation for first AP is going on. So only do_acs is split to
1424 * seperate start_acs routine. Also SME-PMAC struct that is used to
1425 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1426 * config shall be set only from start_acs.
1427 */
1428
1429 /* nla_policy Policy template. Policy not applied as some attributes are
1430 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1431 *
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1435 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1436 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1437 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1438 */
1439
Jeff Johnson1f61b612016-02-12 16:28:33 -08001440 ENTER_DEV(ndev);
1441
Anurag Chouhan6d760662016-02-20 16:05:43 +05301442 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 hdd_err("Command not allowed in FTM mode");
1444 return -EPERM;
1445 }
1446
1447 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001448 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449 return -EPERM;
1450 }
1451
1452 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301453 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301455
Naveen Rawat64e477e2016-05-20 10:34:56 -07001456 if (cds_is_sub_20_mhz_enabled()) {
1457 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1458 status = -EINVAL;
1459 goto out;
1460 }
1461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301463 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001464
1465 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1466 NULL);
1467 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001468 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469 goto out;
1470 }
1471
1472 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001473 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 goto out;
1475 }
1476 sap_config->acs_cfg.hw_mode = nla_get_u8(
1477 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1478
1479 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1480 ht_enabled =
1481 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1482 else
1483 ht_enabled = 0;
1484
1485 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1486 ht40_enabled =
1487 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1488 else
1489 ht40_enabled = 0;
1490
1491 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1492 vht_enabled =
1493 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1494 else
1495 vht_enabled = 0;
1496
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301497 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1498 vht_enabled = 0;
1499 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1500 }
1501
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1503 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1504 } else {
1505 if (ht_enabled && ht40_enabled)
1506 ch_width = 40;
1507 else
1508 ch_width = 20;
1509 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301510
1511 /* this may be possible, when sap_force_11n_for_11ac is set */
1512 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1513 if (ht_enabled && ht40_enabled)
1514 ch_width = 40;
1515 else
1516 ch_width = 20;
1517 }
1518
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 if (ch_width == 80)
1520 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1521 else if (ch_width == 40)
1522 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1523 else
1524 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1525
1526 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1527 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1528 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1529 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1530 * since it contains the frequency values of the channels in
1531 * the channel list.
1532 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1533 * is present
1534 */
1535 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1536 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1537 sap_config->acs_cfg.ch_list_count = nla_len(
1538 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1539 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301540 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 sizeof(uint8_t) *
1542 sap_config->acs_cfg.ch_list_count);
1543 if (sap_config->acs_cfg.ch_list == NULL)
1544 goto out;
1545
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301546 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 sap_config->acs_cfg.ch_list_count);
1548 }
1549 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1550 uint32_t *freq =
1551 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1552 sap_config->acs_cfg.ch_list_count = nla_len(
1553 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1554 sizeof(uint32_t);
1555 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301556 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 sap_config->acs_cfg.ch_list_count);
1558 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001559 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001560 status = -ENOMEM;
1561 goto out;
1562 }
1563
1564 /* convert frequency to channel */
1565 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1566 sap_config->acs_cfg.ch_list[i] =
1567 ieee80211_frequency_to_channel(freq[i]);
1568 }
1569 }
1570
1571 hdd_debug("get pcl for DO_ACS vendor command");
1572
1573 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001574 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301575 sap_config->acs_cfg.pcl_channels,
1576 &sap_config->acs_cfg.pcl_ch_count,
1577 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301578 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001579 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301582 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1583 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001584 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001585 vht_enabled = 1;
1586 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1587 sap_config->acs_cfg.ch_width =
1588 hdd_ctx->config->vhtChannelWidth;
1589 /* No VHT80 in 2.4G so perform ACS accordingly */
1590 if (sap_config->acs_cfg.end_ch <= 14 &&
1591 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1592 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1593 }
1594
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301595 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1596
Jeff Johnson020db452016-06-29 14:37:26 -07001597 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 -08001598 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1599 ch_width, ht_enabled, vht_enabled,
1600 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1601
1602 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001603 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604 sap_config->acs_cfg.ch_list_count);
1605 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001606 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 }
1608 sap_config->acs_cfg.acs_mode = true;
1609 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001610 /* ***Note*** Completion variable usage is not allowed
1611 * here since ACS scan operation may take max 2.2 sec
1612 * for 5G band:
1613 * 9 Active channel X 40 ms active scan time +
1614 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1616 * for this long. So we split up the scanning part.
1617 */
1618 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001619 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001620 status = 0;
1621 } else {
1622 status = wlan_hdd_cfg80211_start_acs(adapter);
1623 }
1624
1625out:
1626 if (0 == status) {
1627 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1628 NLMSG_HDRLEN);
1629 if (temp_skbuff != NULL)
1630 return cfg80211_vendor_cmd_reply(temp_skbuff);
1631 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001632 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001633 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1634
1635 return status;
1636}
1637
1638 /**
1639 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1640 * @wiphy: Linux wiphy struct pointer
1641 * @wdev: Linux wireless device struct pointer
1642 * @data: ACS information from hostapd
1643 * @data_len: ACS information len
1644 *
1645 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1646 * and starts ACS procedure.
1647 *
1648 * Return: ACS procedure start status
1649 */
1650
1651static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1652 struct wireless_dev *wdev,
1653 const void *data, int data_len)
1654{
1655 int ret;
1656
1657 cds_ssr_protect(__func__);
1658 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1659 cds_ssr_unprotect(__func__);
1660
1661 return ret;
1662}
1663
1664/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001665 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1666 * @adapter: Pointer to adapter struct
1667 *
1668 * This function handle cleanup of what was done in DO_ACS, including free
1669 * memory.
1670 *
1671 * Return: void
1672 */
1673
1674void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1675{
1676 if (adapter == NULL)
1677 return;
1678 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1679 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1680 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1681 }
1682}
1683
1684/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1686 * @work: Linux workqueue struct pointer for ACS work
1687 *
1688 * This function starts the ACS procedure which was marked pending when an ACS
1689 * procedure was in progress for a concurrent SAP interface.
1690 *
1691 * Return: None
1692 */
1693
1694static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1695{
1696 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1697 acs_pending_work.work);
1698 wlan_hdd_cfg80211_start_acs(adapter);
1699}
1700
1701/**
1702 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1703 * @adapter: Pointer to SAP adapter struct
1704 * @pri_channel: SAP ACS procedure selected Primary channel
1705 * @sec_channel: SAP ACS procedure selected secondary channel
1706 *
1707 * This is a callback function from SAP module on ACS procedure is completed.
1708 * This function send the ACS selected channel information to hostapd
1709 *
1710 * Return: None
1711 */
1712
1713void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1714{
1715 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1716 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1717 struct sk_buff *vendor_event;
1718 int ret_val;
1719 hdd_adapter_t *con_sap_adapter;
1720 uint16_t ch_width;
1721
1722 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001723 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1725 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1726 GFP_KERNEL);
1727
1728 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001729 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 return;
1731 }
1732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 ret_val = nla_put_u8(vendor_event,
1734 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1735 sap_cfg->acs_cfg.pri_ch);
1736 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001737 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 kfree_skb(vendor_event);
1739 return;
1740 }
1741
1742 ret_val = nla_put_u8(vendor_event,
1743 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1744 sap_cfg->acs_cfg.ht_sec_ch);
1745 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001746 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001747 kfree_skb(vendor_event);
1748 return;
1749 }
1750
1751 ret_val = nla_put_u8(vendor_event,
1752 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1753 sap_cfg->acs_cfg.vht_seg0_center_ch);
1754 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001755 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756 kfree_skb(vendor_event);
1757 return;
1758 }
1759
1760 ret_val = nla_put_u8(vendor_event,
1761 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1762 sap_cfg->acs_cfg.vht_seg1_center_ch);
1763 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001764 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765 kfree_skb(vendor_event);
1766 return;
1767 }
1768
1769 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1770 ch_width = 80;
1771 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1772 ch_width = 40;
1773 else
1774 ch_width = 20;
1775
1776 ret_val = nla_put_u16(vendor_event,
1777 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1778 ch_width);
1779 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001780 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781 kfree_skb(vendor_event);
1782 return;
1783 }
1784 if (sap_cfg->acs_cfg.pri_ch > 14)
1785 ret_val = nla_put_u8(vendor_event,
1786 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1787 QCA_ACS_MODE_IEEE80211A);
1788 else
1789 ret_val = nla_put_u8(vendor_event,
1790 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1791 QCA_ACS_MODE_IEEE80211G);
1792
1793 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001794 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 kfree_skb(vendor_event);
1796 return;
1797 }
1798
Jeff Johnson46b40792016-06-29 14:03:14 -07001799 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 -08001800 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1801 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1802 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1803
1804 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1805 /* ***Note*** As already mentioned Completion variable usage is not
1806 * allowed here since ACS scan operation may take max 2.2 sec.
1807 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1808 * operation.
1809 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1810 * when Primary AP ACS is complete and secondary AP ACS is started here
1811 * immediately, Primary AP start_bss may come inbetween ACS operation
1812 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1813 * delay. This path and below constraint will be removed on sessionizing
1814 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1815 * As per design constraint user space control application must take
1816 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1817 * this code path. Sec AP hostapd should be started after Primary AP
1818 * start beaconing which can be confirmed by getchannel iwpriv command
1819 */
1820
1821 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1822 if (con_sap_adapter &&
1823 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1825 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 /* Lets give 500ms for OBSS + START_BSS to complete */
1827 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1828 msecs_to_jiffies(500));
1829 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1830 }
1831
1832 return;
1833}
1834
1835static int
1836__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1837 struct wireless_dev *wdev,
1838 const void *data,
1839 int data_len)
1840{
1841 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1842 struct sk_buff *skb = NULL;
1843 uint32_t fset = 0;
1844 int ret;
1845
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001846 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301847
Anurag Chouhan6d760662016-02-20 16:05:43 +05301848 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001849 hdd_err("Command not allowed in FTM mode");
1850 return -EPERM;
1851 }
1852
1853 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301854 if (ret)
1855 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856
1857 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001858 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859 fset |= WIFI_FEATURE_INFRA;
1860 }
1861 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001862 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001863 fset |= WIFI_FEATURE_INFRA_5G;
1864 }
1865#ifdef WLAN_FEATURE_P2P
1866 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1867 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001868 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 fset |= WIFI_FEATURE_P2P;
1870 }
1871#endif
1872 fset |= WIFI_FEATURE_SOFT_AP;
1873
1874 /* HOTSPOT is a supplicant feature, enable it by default */
1875 fset |= WIFI_FEATURE_HOTSPOT;
1876
1877#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301878 if (pHddCtx->config->extscan_enabled &&
1879 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001880 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1882 }
1883#endif
1884 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001885 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 fset |= WIFI_FEATURE_NAN;
1887 }
1888 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001889 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 fset |= WIFI_FEATURE_D2D_RTT;
1891 fset |= WIFI_FEATURE_D2AP_RTT;
1892 }
1893#ifdef FEATURE_WLAN_SCAN_PNO
1894 if (pHddCtx->config->configPNOScanSupport &&
1895 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001896 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 fset |= WIFI_FEATURE_PNO;
1898 }
1899#endif
1900 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1901#ifdef FEATURE_WLAN_TDLS
1902 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1903 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001904 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 fset |= WIFI_FEATURE_TDLS;
1906 }
1907 if (sme_is_feature_supported_by_fw(TDLS) &&
1908 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1909 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001910 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1912 }
1913#endif
1914#ifdef WLAN_AP_STA_CONCURRENCY
1915 fset |= WIFI_FEATURE_AP_STA;
1916#endif
1917 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001918 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919
1920 if (hdd_link_layer_stats_supported())
1921 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1922
1923 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1924 NLMSG_HDRLEN);
1925 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001926 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 return -EINVAL;
1928 }
Jeff Johnson020db452016-06-29 14:37:26 -07001929 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001931 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 goto nla_put_failure;
1933 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301934 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301935 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936nla_put_failure:
1937 kfree_skb(skb);
1938 return -EINVAL;
1939}
1940
1941/**
1942 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1943 * @wiphy: pointer to wireless wiphy structure.
1944 * @wdev: pointer to wireless_dev structure.
1945 * @data: Pointer to the data to be passed via vendor interface
1946 * @data_len:Length of the data to be passed
1947 *
1948 * Return: Return the Success or Failure code.
1949 */
1950static int
1951wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1952 struct wireless_dev *wdev,
1953 const void *data, int data_len)
1954{
1955 int ret = 0;
1956
1957 cds_ssr_protect(__func__);
1958 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1959 data, data_len);
1960 cds_ssr_unprotect(__func__);
1961
1962 return ret;
1963}
1964
1965/**
1966 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1967 * @wiphy: pointer to wireless wiphy structure.
1968 * @wdev: pointer to wireless_dev structure.
1969 * @data: Pointer to the data to be passed via vendor interface
1970 * @data_len:Length of the data to be passed
1971 *
1972 * Set the MAC address that is to be used for scanning.
1973 *
1974 * Return: Return the Success or Failure code.
1975 */
1976static int
1977__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1978 struct wireless_dev *wdev,
1979 const void *data,
1980 int data_len)
1981{
1982 tpSirScanMacOui pReqMsg = NULL;
1983 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301985 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 int ret;
1987
Jeff Johnson1f61b612016-02-12 16:28:33 -08001988 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989
Anurag Chouhan6d760662016-02-20 16:05:43 +05301990 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 hdd_err("Command not allowed in FTM mode");
1992 return -EPERM;
1993 }
1994
1995 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301996 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998
1999 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002000 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001 return -ENOTSUPP;
2002 }
2003
2004 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2005 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002006 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 return -EINVAL;
2008 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302009 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002011 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 return -ENOMEM;
2013 }
2014 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002015 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 goto fail;
2017 }
2018 nla_memcpy(&pReqMsg->oui[0],
2019 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2020 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002021 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 pReqMsg->oui[1], pReqMsg->oui[2]);
2023 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302024 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002025 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 goto fail;
2027 }
2028 return 0;
2029fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302030 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031 return -EINVAL;
2032}
2033
2034/**
2035 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2036 * @wiphy: pointer to wireless wiphy structure.
2037 * @wdev: pointer to wireless_dev structure.
2038 * @data: Pointer to the data to be passed via vendor interface
2039 * @data_len:Length of the data to be passed
2040 *
2041 * Set the MAC address that is to be used for scanning. This is an
2042 * SSR-protecting wrapper function.
2043 *
2044 * Return: Return the Success or Failure code.
2045 */
2046static int
2047wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2048 struct wireless_dev *wdev,
2049 const void *data,
2050 int data_len)
2051{
2052 int ret;
2053
2054 cds_ssr_protect(__func__);
2055 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2056 data, data_len);
2057 cds_ssr_unprotect(__func__);
2058
2059 return ret;
2060}
2061
2062/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302063 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2064 * @wiphy: pointer phy adapter
2065 * @wdev: pointer to wireless device structure
2066 * @data: pointer to data buffer
2067 * @data_len: length of data
2068 *
2069 * This routine will give concurrency matrix
2070 *
2071 * Return: int status code
2072 */
2073static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2074 struct wireless_dev *wdev,
2075 const void *data,
2076 int data_len)
2077{
2078 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2079 uint8_t i, feature_sets, max_feature_sets;
2080 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2081 struct sk_buff *reply_skb;
2082 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2083 int ret;
2084
2085 ENTER_DEV(wdev->netdev);
2086
2087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2088 hdd_err("Command not allowed in FTM mode");
2089 return -EPERM;
2090 }
2091
2092 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302093 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302094 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302095
2096 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2097 data, data_len, NULL)) {
2098 hdd_err("Invalid ATTR");
2099 return -EINVAL;
2100 }
2101
2102 /* Parse and fetch max feature set */
2103 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2104 hdd_err("Attr max feature set size failed");
2105 return -EINVAL;
2106 }
2107 max_feature_sets = nla_get_u32(tb[
2108 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2109 hdd_info("Max feature set size: %d", max_feature_sets);
2110
2111 /* Fill feature combination matrix */
2112 feature_sets = 0;
2113 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002114 WIFI_FEATURE_P2P;
2115 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2116 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302117 /* Add more feature combinations here */
2118
2119 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002120 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302121 hdd_info("Feature set matrix");
2122 for (i = 0; i < feature_sets; i++)
2123 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2124
2125 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2126 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2127 if (!reply_skb) {
2128 hdd_err("Feature set matrix: buffer alloc fail");
2129 return -ENOMEM;
2130 }
2131
2132 if (nla_put_u32(reply_skb,
2133 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2134 feature_sets) ||
2135 nla_put(reply_skb,
2136 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2137 sizeof(u32) * feature_sets,
2138 feature_set_matrix)) {
2139 hdd_err("nla put fail");
2140 kfree_skb(reply_skb);
2141 return -EINVAL;
2142 }
2143 return cfg80211_vendor_cmd_reply(reply_skb);
2144}
2145
2146/**
2147 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2148 * @wiphy: pointer to wireless wiphy structure.
2149 * @wdev: pointer to wireless_dev structure.
2150 * @data: Pointer to the data to be passed via vendor interface
2151 * @data_len:Length of the data to be passed
2152 *
2153 * Retrieves the concurrency feature set matrix
2154 *
2155 * Return: 0 on success, negative errno on failure
2156 */
2157static int
2158wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2159 struct wireless_dev *wdev,
2160 const void *data,
2161 int data_len)
2162{
2163 int ret;
2164
2165 cds_ssr_protect(__func__);
2166 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2167 data, data_len);
2168 cds_ssr_unprotect(__func__);
2169
2170 return ret;
2171}
2172
2173/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2175 * @feature_flags: pointer to the byte array of features.
2176 * @feature: Feature to be turned ON in the byte array.
2177 *
2178 * Return: None
2179 *
2180 * This is called to turn ON or SET the feature flag for the requested feature.
2181 **/
2182#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002183static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2184 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185{
2186 uint32_t index;
2187 uint8_t bit_mask;
2188
2189 index = feature / NUM_BITS_IN_BYTE;
2190 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2191 feature_flags[index] |= bit_mask;
2192}
2193
2194/**
2195 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2196 * @wiphy: pointer to wireless wiphy structure.
2197 * @wdev: pointer to wireless_dev structure.
2198 * @data: Pointer to the data to be passed via vendor interface
2199 * @data_len:Length of the data to be passed
2200 *
2201 * This is called when wlan driver needs to send supported feature set to
2202 * supplicant upon a request/query from the supplicant.
2203 *
2204 * Return: Return the Success or Failure code.
2205 **/
2206#define MAX_CONCURRENT_CHAN_ON_24G 2
2207#define MAX_CONCURRENT_CHAN_ON_5G 2
2208static int
2209__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2210 struct wireless_dev *wdev,
2211 const void *data, int data_len)
2212{
2213 struct sk_buff *skb = NULL;
2214 uint32_t dbs_capability = 0;
2215 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302216 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217 int ret_val;
2218
2219 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2220 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2221
Jeff Johnson1f61b612016-02-12 16:28:33 -08002222 ENTER_DEV(wdev->netdev);
2223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2225 if (ret_val)
2226 return ret_val;
2227
Anurag Chouhan6d760662016-02-20 16:05:43 +05302228 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 hdd_err("Command not allowed in FTM mode");
2230 return -EPERM;
2231 }
2232
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002233 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002234 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 wlan_hdd_cfg80211_set_feature(feature_flags,
2236 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2237 }
2238
2239 wlan_hdd_cfg80211_set_feature(feature_flags,
2240 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2241 if (wma_is_scan_simultaneous_capable())
2242 wlan_hdd_cfg80211_set_feature(feature_flags,
2243 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002244
2245 if (wma_is_p2p_lo_capable())
2246 wlan_hdd_cfg80211_set_feature(feature_flags,
2247 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2248
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2250 NLMSG_HDRLEN);
2251
2252 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002253 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 return -ENOMEM;
2255 }
2256
2257 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2258 sizeof(feature_flags), feature_flags))
2259 goto nla_put_failure;
2260
2261 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302262 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002263 if (one_by_one_dbs)
2264 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2265
2266 if (two_by_two_dbs)
2267 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2268
2269 if (!one_by_one_dbs && !two_by_two_dbs)
2270 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2271 } else {
2272 hdd_err("wma_get_dbs_hw_mode failed");
2273 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2274 }
2275
2276 hdd_info("dbs_capability is %d", dbs_capability);
2277
2278 if (nla_put_u32(skb,
2279 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2280 MAX_CONCURRENT_CHAN_ON_24G))
2281 goto nla_put_failure;
2282
2283 if (nla_put_u32(skb,
2284 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2285 MAX_CONCURRENT_CHAN_ON_5G))
2286 goto nla_put_failure;
2287
2288 return cfg80211_vendor_cmd_reply(skb);
2289
2290nla_put_failure:
2291 kfree_skb(skb);
2292 return -EINVAL;
2293}
2294
2295/**
2296 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2297 * @wiphy: pointer to wireless wiphy structure.
2298 * @wdev: pointer to wireless_dev structure.
2299 * @data: Pointer to the data to be passed via vendor interface
2300 * @data_len:Length of the data to be passed
2301 *
2302 * This is called when wlan driver needs to send supported feature set to
2303 * supplicant upon a request/query from the supplicant.
2304 *
2305 * Return: Return the Success or Failure code.
2306 */
2307static int
2308wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2309 struct wireless_dev *wdev,
2310 const void *data, int data_len)
2311{
2312 int ret;
2313
2314 cds_ssr_protect(__func__);
2315 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2316 data, data_len);
2317 cds_ssr_unprotect(__func__);
2318
2319 return ret;
2320}
2321
2322
2323/**
2324 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2325 * @wiphy: The wiphy structure
2326 * @wdev: The wireless device
2327 * @data: Data passed by framework
2328 * @data_len: Parameters to be configured passed as data
2329 *
2330 * The roaming related parameters are configured by the framework
2331 * using this interface.
2332 *
2333 * Return: Return either success or failure code.
2334 */
2335static int
2336__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2337 struct wireless_dev *wdev, const void *data, int data_len)
2338{
2339 struct net_device *dev = wdev->netdev;
2340 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2341 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2342 uint8_t session_id;
2343 struct roam_ext_params roam_params;
2344 uint32_t cmd_type, req_id;
2345 struct nlattr *curr_attr;
2346 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2347 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2348 int rem, i;
2349 uint32_t buf_len = 0;
2350 int ret;
2351
Jeff Johnson1f61b612016-02-12 16:28:33 -08002352 ENTER_DEV(dev);
2353
Anurag Chouhan6d760662016-02-20 16:05:43 +05302354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 hdd_err("Command not allowed in FTM mode");
2356 return -EPERM;
2357 }
2358
2359 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302360 if (ret)
2361 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362
2363 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2364 data, data_len,
2365 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002366 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 return -EINVAL;
2368 }
2369 /* Parse and fetch Command Type*/
2370 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002371 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 goto fail;
2373 }
2374 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302375 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2377 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 goto fail;
2380 }
2381 req_id = nla_get_u32(
2382 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002383 hdd_debug("Req Id (%d)", req_id);
2384 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 switch (cmd_type) {
2386 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2387 i = 0;
2388 nla_for_each_nested(curr_attr,
2389 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2390 rem) {
2391 if (nla_parse(tb2,
2392 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2393 nla_data(curr_attr), nla_len(curr_attr),
2394 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 goto fail;
2397 }
2398 /* Parse and Fetch allowed SSID list*/
2399 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002400 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 goto fail;
2402 }
2403 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2404 /*
2405 * Upper Layers include a null termination character.
2406 * Check for the actual permissible length of SSID and
2407 * also ensure not to copy the NULL termination
2408 * character to the driver buffer.
2409 */
2410 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2411 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2412 nla_memcpy(
2413 roam_params.ssid_allowed_list[i].ssId,
2414 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2415 buf_len - 1);
2416 roam_params.ssid_allowed_list[i].length =
2417 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002418 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 roam_params.ssid_allowed_list[i].length,
2420 roam_params.ssid_allowed_list[i].ssId,
2421 roam_params.ssid_allowed_list[i].length);
2422 i++;
2423 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002424 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 }
2426 }
2427 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002428 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 roam_params.num_ssid_allowed_list);
2430 sme_update_roam_params(pHddCtx->hHal, session_id,
2431 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2432 break;
2433 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2434 /* Parse and fetch 5G Boost Threshold */
2435 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002436 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 goto fail;
2438 }
2439 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2440 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002441 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 roam_params.raise_rssi_thresh_5g);
2443 /* Parse and fetch 5G Penalty Threshold */
2444 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002445 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 goto fail;
2447 }
2448 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2449 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002450 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 roam_params.drop_rssi_thresh_5g);
2452 /* Parse and fetch 5G Boost Factor */
2453 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 goto fail;
2456 }
2457 roam_params.raise_factor_5g = nla_get_u32(
2458 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 roam_params.raise_factor_5g);
2461 /* Parse and fetch 5G Penalty factor */
2462 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 goto fail;
2465 }
2466 roam_params.drop_factor_5g = nla_get_u32(
2467 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 roam_params.drop_factor_5g);
2470 /* Parse and fetch 5G Max Boost */
2471 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 goto fail;
2474 }
2475 roam_params.max_raise_rssi_5g = nla_get_u32(
2476 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002477 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 roam_params.max_raise_rssi_5g);
2479 /* Parse and fetch Rssi Diff */
2480 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002481 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 goto fail;
2483 }
2484 roam_params.rssi_diff = nla_get_s32(
2485 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002486 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 roam_params.rssi_diff);
2488 /* Parse and fetch Alert Rssi Threshold */
2489 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002490 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 goto fail;
2492 }
2493 roam_params.alert_rssi_threshold = nla_get_u32(
2494 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002495 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 roam_params.alert_rssi_threshold);
2497 sme_update_roam_params(pHddCtx->hHal, session_id,
2498 roam_params,
2499 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2500 break;
2501 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2502 /* Parse and fetch Activate Good Rssi Roam */
2503 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002504 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002505 goto fail;
2506 }
2507 roam_params.good_rssi_roam = nla_get_s32(
2508 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002509 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510 roam_params.good_rssi_roam);
2511 sme_update_roam_params(pHddCtx->hHal, session_id,
2512 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2513 break;
2514 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2515 /* Parse and fetch number of preferred BSSID */
2516 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002517 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002518 goto fail;
2519 }
2520 roam_params.num_bssid_favored = nla_get_u32(
2521 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002522 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 roam_params.num_bssid_favored);
2524 i = 0;
2525 nla_for_each_nested(curr_attr,
2526 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
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_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002537 hdd_err("attr mac address 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_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_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,
2544 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 /* Parse and fetch preference factor*/
2546 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002547 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 goto fail;
2549 }
2550 roam_params.bssid_favored_factor[i] = nla_get_u32(
2551 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002552 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 roam_params.bssid_favored_factor[i]);
2554 i++;
2555 }
2556 sme_update_roam_params(pHddCtx->hHal, session_id,
2557 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2558 break;
2559 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2560 /* Parse and fetch number of blacklist BSSID */
2561 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002562 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 goto fail;
2564 }
2565 roam_params.num_bssid_avoid_list = nla_get_u32(
2566 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 roam_params.num_bssid_avoid_list);
2569 i = 0;
2570 nla_for_each_nested(curr_attr,
2571 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2572 rem) {
2573 if (nla_parse(tb2,
2574 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2575 nla_data(curr_attr), nla_len(curr_attr),
2576 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002577 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 goto fail;
2579 }
2580 /* Parse and fetch MAC address */
2581 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002582 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 goto fail;
2584 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002585 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302587 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002588 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002590 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 i++;
2592 }
2593 sme_update_roam_params(pHddCtx->hHal, session_id,
2594 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2595 break;
2596 }
2597 return 0;
2598fail:
2599 return -EINVAL;
2600}
2601
2602/**
2603 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2604 * @wiphy: pointer to wireless wiphy structure.
2605 * @wdev: pointer to wireless_dev structure.
2606 * @data: Pointer to the data to be passed via vendor interface
2607 * @data_len:Length of the data to be passed
2608 *
2609 * Return: Return the Success or Failure code.
2610 */
2611static int
2612wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2613 struct wireless_dev *wdev,
2614 const void *data,
2615 int data_len)
2616{
2617 int ret;
2618
2619 cds_ssr_protect(__func__);
2620 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2621 data, data_len);
2622 cds_ssr_unprotect(__func__);
2623
2624 return ret;
2625}
2626
2627static const struct nla_policy
2628wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2629 +1] = {
2630 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2631};
2632
2633/**
2634 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2635 * @hdd_ctx: HDD context
2636 * @device_mode: device mode
2637 * Return: bool
2638 */
2639static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002640 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641{
2642 hdd_adapter_t *adapter;
2643 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2644 hdd_ap_ctx_t *ap_ctx;
2645 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302646 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302648 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 &adapter_node);
2650
2651 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302652 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002653 adapter = adapter_node->pAdapter;
2654
2655 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002656 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 ap_ctx =
2658 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2659
2660 /*
2661 * if there is SAP already running on DFS channel,
2662 * do not disable scan on dfs channels. Note that
2663 * with SAP on DFS, there cannot be conurrency on
2664 * single radio. But then we can have multiple
2665 * radios !!
2666 */
2667 if (CHANNEL_STATE_DFS ==
2668 cds_get_channel_state(
2669 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002670 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 return true;
2672 }
2673 }
2674
2675 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002676 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 sta_ctx =
2678 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2679
2680 /*
2681 * if STA is already connected on DFS channel,
2682 * do not disable scan on dfs channels
2683 */
2684 if (hdd_conn_is_connected(sta_ctx) &&
2685 (CHANNEL_STATE_DFS ==
2686 cds_get_channel_state(
2687 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002688 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 return true;
2690 }
2691 }
2692
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302693 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002694 adapter_node,
2695 &next);
2696 adapter_node = next;
2697 }
2698
2699 return false;
2700}
2701
2702/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002703 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2704 * @hdd_ctx: HDD context within host driver
2705 * @adapter: Adapter pointer
2706 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2707 *
2708 * Loops through devices to see who is operating on DFS channels
2709 * and then disables/enables DFS channels by calling SME API.
2710 * Fails the disable request if any device is active on a DFS channel.
2711 *
2712 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002714
2715int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2716 hdd_adapter_t *adapter,
2717 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002719 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722
2723 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2724 if (no_dfs_flag) {
2725 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002726 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727
2728 if (true == status)
2729 return -EOPNOTSUPP;
2730
2731 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002732 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733
2734 if (true == status)
2735 return -EOPNOTSUPP;
2736 }
2737
2738 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2739
2740 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2741
2742 /*
2743 * call the SME API to tunnel down the new channel list
2744 * to the firmware
2745 */
2746 status = sme_handle_dfs_chan_scan(
2747 h_hal, hdd_ctx->config->enableDFSChnlScan);
2748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302749 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 ret_val = 0;
2751
2752 /*
2753 * Clear the SME scan cache also. Note that the
2754 * clearing of scan results is independent of session;
2755 * so no need to iterate over
2756 * all sessions
2757 */
2758 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302759 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760 ret_val = -EPERM;
2761 }
2762
2763 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002764 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765 ret_val = 0;
2766 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002767 return ret_val;
2768}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002770/**
2771 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2772 * @wiphy: corestack handler
2773 * @wdev: wireless device
2774 * @data: data
2775 * @data_len: data length
2776 * Return: success(0) or reason code for failure
2777 */
2778static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2779 struct wireless_dev *wdev,
2780 const void *data,
2781 int data_len)
2782{
2783 struct net_device *dev = wdev->netdev;
2784 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2785 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2786 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2787 int ret_val;
2788 uint32_t no_dfs_flag = 0;
2789
Jeff Johnson1f61b612016-02-12 16:28:33 -08002790 ENTER_DEV(dev);
2791
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002792 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302793 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002794 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002795
2796 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2797 data, data_len,
2798 wlan_hdd_set_no_dfs_flag_config_policy)) {
2799 hdd_err("invalid attr");
2800 return -EINVAL;
2801 }
2802
2803 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2804 hdd_err("attr dfs flag failed");
2805 return -EINVAL;
2806 }
2807
2808 no_dfs_flag = nla_get_u32(
2809 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2810
Jeff Johnson020db452016-06-29 14:37:26 -07002811 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002812
2813 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002814 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002815 return -EINVAL;
2816 }
2817
2818 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2819 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 return ret_val;
2821}
2822
2823/**
2824 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2825 *
2826 * @wiphy: wiphy device pointer
2827 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002828 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 * @data_len: Buffer length
2830 *
2831 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2832 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2833 *
2834 * Return: EOK or other error codes.
2835 */
2836
2837static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2838 struct wireless_dev *wdev,
2839 const void *data,
2840 int data_len)
2841{
2842 int ret;
2843
2844 cds_ssr_protect(__func__);
2845 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2846 data, data_len);
2847 cds_ssr_unprotect(__func__);
2848
2849 return ret;
2850}
2851
Manikandan Mohan80dea792016-04-28 16:36:48 -07002852static const struct nla_policy
2853wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2854 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2855};
2856
2857/**
2858 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2859 * @wiphy: wiphy device pointer
2860 * @wdev: wireless device pointer
2861 * @data: Vendor command data buffer
2862 * @data_len: Buffer length
2863 *
2864 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2865 * setup WISA Mode features.
2866 *
2867 * Return: Success(0) or reason code for failure
2868 */
2869static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2870 struct wireless_dev *wdev, const void *data, int data_len)
2871{
2872 struct net_device *dev = wdev->netdev;
2873 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2874 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2875 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2876 struct sir_wisa_params wisa;
2877 int ret_val;
2878 QDF_STATUS status;
2879 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002880 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2881 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002882
2883 ENTER_DEV(dev);
2884 ret_val = wlan_hdd_validate_context(hdd_ctx);
2885 if (ret_val)
2886 goto err;
2887
2888 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2889 hdd_err("Command not allowed in FTM mode");
2890 return -EPERM;
2891 }
2892
2893 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2894 wlan_hdd_wisa_cmd_policy)) {
2895 hdd_err("Invalid WISA cmd attributes");
2896 ret_val = -EINVAL;
2897 goto err;
2898 }
2899 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2900 hdd_err("Invalid WISA mode");
2901 ret_val = -EINVAL;
2902 goto err;
2903 }
2904
2905 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2906 hdd_info("WISA Mode: %d", wisa_mode);
2907 wisa.mode = wisa_mode;
2908 wisa.vdev_id = adapter->sessionId;
2909 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002910 if (!QDF_IS_STATUS_SUCCESS(status)) {
2911 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002912 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002913 }
2914 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002915 cdp_set_wisa_mode(soc,
2916 cdp_get_vdev_from_vdev_id(soc, pdev,
2917 adapter->sessionId),
2918 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002919err:
2920 EXIT();
2921 return ret_val;
2922}
2923
2924/**
2925 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2926 * @wiphy: corestack handler
2927 * @wdev: wireless device
2928 * @data: data
2929 * @data_len: data length
2930 *
2931 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2932 * setup WISA mode features.
2933 *
2934 * Return: Success(0) or reason code for failure
2935 */
2936static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2937 struct wireless_dev *wdev,
2938 const void *data,
2939 int data_len)
2940{
2941 int ret;
2942
2943 cds_ssr_protect(__func__);
2944 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2945 cds_ssr_unprotect(__func__);
2946
2947 return ret;
2948}
2949
Anurag Chouhan96919482016-07-13 16:36:57 +05302950/*
2951 * define short names for the global vendor params
2952 * used by __wlan_hdd_cfg80211_get_station_cmd()
2953 */
2954#define STATION_INVALID \
2955 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2956#define STATION_INFO \
2957 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2958#define STATION_ASSOC_FAIL_REASON \
2959 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2960#define STATION_MAX \
2961 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2962
2963static const struct nla_policy
2964hdd_get_station_policy[STATION_MAX + 1] = {
2965 [STATION_INFO] = {.type = NLA_FLAG},
2966 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2967};
2968
2969/**
2970 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2971 * @hdd_ctx: HDD context within host driver
2972 * @wdev: wireless device
2973 *
2974 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2975 * Validate cmd attributes and send the station info to upper layers.
2976 *
2977 * Return: Success(0) or reason code for failure
2978 */
2979static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2980 hdd_adapter_t *adapter)
2981{
2982 struct sk_buff *skb = NULL;
2983 uint32_t nl_buf_len;
2984 hdd_station_ctx_t *hdd_sta_ctx;
2985
2986 nl_buf_len = NLMSG_HDRLEN;
2987 nl_buf_len += sizeof(uint32_t);
2988 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2989
2990 if (!skb) {
2991 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2992 return -ENOMEM;
2993 }
2994
2995 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2996
2997 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2998 hdd_sta_ctx->conn_info.assoc_status_code)) {
2999 hdd_err("put fail");
3000 goto fail;
3001 }
3002 return cfg80211_vendor_cmd_reply(skb);
3003fail:
3004 if (skb)
3005 kfree_skb(skb);
3006 return -EINVAL;
3007}
3008
3009/**
3010 * hdd_map_auth_type() - transform auth type specific to
3011 * vendor command
3012 * @auth_type: csr auth type
3013 *
3014 * Return: Success(0) or reason code for failure
3015 */
3016static int hdd_convert_auth_type(uint32_t auth_type)
3017{
3018 uint32_t ret_val;
3019
3020 switch (auth_type) {
3021 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3022 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3023 break;
3024 case eCSR_AUTH_TYPE_SHARED_KEY:
3025 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3026 break;
3027 case eCSR_AUTH_TYPE_WPA:
3028 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3029 break;
3030 case eCSR_AUTH_TYPE_WPA_PSK:
3031 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3032 break;
3033 case eCSR_AUTH_TYPE_AUTOSWITCH:
3034 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3035 break;
3036 case eCSR_AUTH_TYPE_WPA_NONE:
3037 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3038 break;
3039 case eCSR_AUTH_TYPE_RSN:
3040 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3041 break;
3042 case eCSR_AUTH_TYPE_RSN_PSK:
3043 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3044 break;
3045 case eCSR_AUTH_TYPE_FT_RSN:
3046 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3047 break;
3048 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3049 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3050 break;
3051 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3052 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3053 break;
3054 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3055 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3056 break;
3057 case eCSR_AUTH_TYPE_CCKM_WPA:
3058 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3059 break;
3060 case eCSR_AUTH_TYPE_CCKM_RSN:
3061 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3062 break;
3063 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3064 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3065 break;
3066 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3067 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3068 break;
3069 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3070 case eCSR_AUTH_TYPE_FAILED:
3071 case eCSR_AUTH_TYPE_NONE:
3072 default:
3073 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3074 break;
3075 }
3076 return ret_val;
3077}
3078
3079/**
3080 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3081 * vendor command
3082 * @dot11mode: dot11mode
3083 *
3084 * Return: Success(0) or reason code for failure
3085 */
3086static int hdd_convert_dot11mode(uint32_t dot11mode)
3087{
3088 uint32_t ret_val;
3089
3090 switch (dot11mode) {
3091 case eCSR_CFG_DOT11_MODE_11A:
3092 ret_val = QCA_WLAN_802_11_MODE_11A;
3093 break;
3094 case eCSR_CFG_DOT11_MODE_11B:
3095 ret_val = QCA_WLAN_802_11_MODE_11B;
3096 break;
3097 case eCSR_CFG_DOT11_MODE_11G:
3098 ret_val = QCA_WLAN_802_11_MODE_11G;
3099 break;
3100 case eCSR_CFG_DOT11_MODE_11N:
3101 ret_val = QCA_WLAN_802_11_MODE_11N;
3102 break;
3103 case eCSR_CFG_DOT11_MODE_11AC:
3104 ret_val = QCA_WLAN_802_11_MODE_11AC;
3105 break;
3106 case eCSR_CFG_DOT11_MODE_AUTO:
3107 case eCSR_CFG_DOT11_MODE_ABG:
3108 default:
3109 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3110 }
3111 return ret_val;
3112}
3113
3114/**
3115 * hdd_add_tx_bitrate() - add tx bitrate attribute
3116 * @skb: pointer to sk buff
3117 * @hdd_sta_ctx: pointer to hdd station context
3118 * @idx: attribute index
3119 *
3120 * Return: Success(0) or reason code for failure
3121 */
3122static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3123 hdd_station_ctx_t *hdd_sta_ctx,
3124 int idx)
3125{
3126 struct nlattr *nla_attr;
3127 uint32_t bitrate, bitrate_compat;
3128
3129 nla_attr = nla_nest_start(skb, idx);
3130 if (!nla_attr)
3131 goto fail;
3132 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3133 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3134
3135 /* report 16-bit bitrate only if we can */
3136 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3137 if (bitrate > 0 &&
3138 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3139 hdd_err("put fail");
3140 goto fail;
3141 }
3142 if (bitrate_compat > 0 &&
3143 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3144 hdd_err("put fail");
3145 goto fail;
3146 }
3147 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3148 hdd_sta_ctx->conn_info.txrate.nss)) {
3149 hdd_err("put fail");
3150 goto fail;
3151 }
3152 nla_nest_end(skb, nla_attr);
3153 return 0;
3154fail:
3155 return -EINVAL;
3156}
3157
3158/**
3159 * hdd_add_sta_info() - add station info attribute
3160 * @skb: pointer to sk buff
3161 * @hdd_sta_ctx: pointer to hdd station context
3162 * @idx: attribute index
3163 *
3164 * Return: Success(0) or reason code for failure
3165 */
3166static int32_t hdd_add_sta_info(struct sk_buff *skb,
3167 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3168{
3169 struct nlattr *nla_attr;
3170
3171 nla_attr = nla_nest_start(skb, idx);
3172 if (!nla_attr)
3173 goto fail;
3174 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3175 (hdd_sta_ctx->conn_info.signal + 100))) {
3176 hdd_err("put fail");
3177 goto fail;
3178 }
3179 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3180 goto fail;
3181 nla_nest_end(skb, nla_attr);
3182 return 0;
3183fail:
3184 return -EINVAL;
3185}
3186
3187/**
3188 * hdd_add_survey_info() - add survey info attribute
3189 * @skb: pointer to sk buff
3190 * @hdd_sta_ctx: pointer to hdd station context
3191 * @idx: attribute index
3192 *
3193 * Return: Success(0) or reason code for failure
3194 */
3195static int32_t hdd_add_survey_info(struct sk_buff *skb,
3196 hdd_station_ctx_t *hdd_sta_ctx,
3197 int idx)
3198{
3199 struct nlattr *nla_attr;
3200
3201 nla_attr = nla_nest_start(skb, idx);
3202 if (!nla_attr)
3203 goto fail;
3204 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3205 hdd_sta_ctx->conn_info.freq) ||
3206 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3207 (hdd_sta_ctx->conn_info.noise + 100))) {
3208 hdd_err("put fail");
3209 goto fail;
3210 }
3211 nla_nest_end(skb, nla_attr);
3212 return 0;
3213fail:
3214 return -EINVAL;
3215}
3216
3217/**
3218 * hdd_add_link_standard_info() - add link info attribute
3219 * @skb: pointer to sk buff
3220 * @hdd_sta_ctx: pointer to hdd station context
3221 * @idx: attribute index
3222 *
3223 * Return: Success(0) or reason code for failure
3224 */
3225static int32_t
3226hdd_add_link_standard_info(struct sk_buff *skb,
3227 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3228{
3229 struct nlattr *nla_attr;
3230
3231 nla_attr = nla_nest_start(skb, idx);
3232 if (!nla_attr)
3233 goto fail;
3234 if (nla_put(skb,
3235 NL80211_ATTR_SSID,
3236 hdd_sta_ctx->conn_info.SSID.SSID.length,
3237 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3238 hdd_err("put fail");
3239 goto fail;
3240 }
3241 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3242 goto fail;
3243 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3244 goto fail;
3245 nla_nest_end(skb, nla_attr);
3246 return 0;
3247fail:
3248 return -EINVAL;
3249}
3250
3251/**
3252 * hdd_add_ap_standard_info() - add ap info attribute
3253 * @skb: pointer to sk buff
3254 * @hdd_sta_ctx: pointer to hdd station context
3255 * @idx: attribute index
3256 *
3257 * Return: Success(0) or reason code for failure
3258 */
3259static int32_t
3260hdd_add_ap_standard_info(struct sk_buff *skb,
3261 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3262{
3263 struct nlattr *nla_attr;
3264
3265 nla_attr = nla_nest_start(skb, idx);
3266 if (!nla_attr)
3267 goto fail;
3268 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3269 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3270 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3271 &hdd_sta_ctx->conn_info.vht_caps)) {
3272 hdd_err("put fail");
3273 goto fail;
3274 }
3275 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3276 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3277 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3278 &hdd_sta_ctx->conn_info.ht_caps)) {
3279 hdd_err("put fail");
3280 goto fail;
3281 }
3282 nla_nest_end(skb, nla_attr);
3283 return 0;
3284fail:
3285 return -EINVAL;
3286}
3287
3288/**
3289 * hdd_get_station_info() - send BSS information to supplicant
3290 * @hdd_ctx: pointer to hdd context
3291 * @adapter: pointer to adapter
3292 *
3293 * Return: 0 if success else error status
3294 */
3295static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3296 hdd_adapter_t *adapter)
3297{
3298 struct sk_buff *skb = NULL;
3299 uint8_t *tmp_hs20 = NULL;
3300 uint32_t nl_buf_len;
3301 hdd_station_ctx_t *hdd_sta_ctx;
3302
3303 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3304
3305 nl_buf_len = NLMSG_HDRLEN;
3306 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3307 sizeof(hdd_sta_ctx->conn_info.freq) +
3308 sizeof(hdd_sta_ctx->conn_info.noise) +
3309 sizeof(hdd_sta_ctx->conn_info.signal) +
3310 (sizeof(uint32_t) * 2) +
3311 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3312 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3313 sizeof(hdd_sta_ctx->conn_info.authType) +
3314 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3315 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3316 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3317 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3318 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3319 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3320 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3321 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3322 1);
3323 }
3324 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3325 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3326 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3327 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3328
3329
3330 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3331 if (!skb) {
3332 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3333 return -ENOMEM;
3334 }
3335
3336 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3337 LINK_INFO_STANDARD_NL80211_ATTR)) {
3338 hdd_err("put fail");
3339 goto fail;
3340 }
3341 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3342 AP_INFO_STANDARD_NL80211_ATTR)) {
3343 hdd_err("put fail");
3344 goto fail;
3345 }
3346 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3347 hdd_sta_ctx->conn_info.roam_count) ||
3348 nla_put_u32(skb, INFO_AKM,
3349 hdd_convert_auth_type(
3350 hdd_sta_ctx->conn_info.authType)) ||
3351 nla_put_u32(skb, WLAN802_11_MODE,
3352 hdd_convert_dot11mode(
3353 hdd_sta_ctx->conn_info.dot11Mode))) {
3354 hdd_err("put fail");
3355 goto fail;
3356 }
3357 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3358 if (nla_put(skb, HT_OPERATION,
3359 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3360 &hdd_sta_ctx->conn_info.ht_operation)) {
3361 hdd_err("put fail");
3362 goto fail;
3363 }
3364 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3365 if (nla_put(skb, VHT_OPERATION,
3366 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3367 &hdd_sta_ctx->conn_info.vht_operation)) {
3368 hdd_err("put fail");
3369 goto fail;
3370 }
3371 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3372 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3373 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3374 tmp_hs20 + 1)) {
3375 hdd_err("put fail");
3376 goto fail;
3377 }
3378
3379 return cfg80211_vendor_cmd_reply(skb);
3380fail:
3381 if (skb)
3382 kfree_skb(skb);
3383 return -EINVAL;
3384}
3385
3386/**
3387 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3388 * @wiphy: corestack handler
3389 * @wdev: wireless device
3390 * @data: data
3391 * @data_len: data length
3392 *
3393 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3394 * Validate cmd attributes and send the station info to upper layers.
3395 *
3396 * Return: Success(0) or reason code for failure
3397 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303398static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303399__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3400 struct wireless_dev *wdev,
3401 const void *data,
3402 int data_len)
3403{
3404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3405 struct net_device *dev = wdev->netdev;
3406 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3407 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3408 int32_t status;
3409
3410 ENTER_DEV(dev);
3411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3412 hdd_err("Command not allowed in FTM mode");
3413 status = -EPERM;
3414 goto out;
3415 }
3416
3417 status = wlan_hdd_validate_context(hdd_ctx);
3418 if (0 != status)
3419 goto out;
3420
3421
3422 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3423 data, data_len, NULL);
3424 if (status) {
3425 hdd_err("Invalid ATTR");
3426 goto out;
3427 }
3428
3429 /* Parse and fetch Command Type*/
3430 if (tb[STATION_INFO]) {
3431 status = hdd_get_station_info(hdd_ctx, adapter);
3432 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3433 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3434 } else {
3435 hdd_err("get station info cmd type failed");
3436 status = -EINVAL;
3437 goto out;
3438 }
3439 EXIT();
3440out:
3441 return status;
3442}
3443
3444/**
3445 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3446 * @wiphy: corestack handler
3447 * @wdev: wireless device
3448 * @data: data
3449 * @data_len: data length
3450 *
3451 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3452 * Validate cmd attributes and send the station info to upper layers.
3453 *
3454 * Return: Success(0) or reason code for failure
3455 */
3456static int32_t
3457hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3458 struct wireless_dev *wdev,
3459 const void *data,
3460 int data_len)
3461{
3462 int ret;
3463
3464 cds_ssr_protect(__func__);
3465 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3466 cds_ssr_unprotect(__func__);
3467
3468 return ret;
3469}
3470
3471/*
3472 * undef short names defined for get station command
3473 * used by __wlan_hdd_cfg80211_get_station_cmd()
3474 */
3475#undef STATION_INVALID
3476#undef STATION_INFO
3477#undef STATION_ASSOC_FAIL_REASON
3478#undef STATION_MAX
3479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3481/**
3482 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3483 * @wiphy: pointer to wireless wiphy structure.
3484 * @wdev: pointer to wireless_dev structure.
3485 * @data: Pointer to the Key data
3486 * @data_len:Length of the data passed
3487 *
3488 * This is called when wlan driver needs to save the keys received via
3489 * vendor specific command.
3490 *
3491 * Return: Return the Success or Failure code.
3492 */
3493static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3494 struct wireless_dev *wdev,
3495 const void *data, int data_len)
3496{
3497 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3498 struct net_device *dev = wdev->netdev;
3499 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3500 hdd_context_t *hdd_ctx_ptr;
3501 int status;
3502
Jeff Johnson1f61b612016-02-12 16:28:33 -08003503 ENTER_DEV(dev);
3504
Anurag Chouhan6d760662016-02-20 16:05:43 +05303505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 hdd_err("Command not allowed in FTM mode");
3507 return -EPERM;
3508 }
3509
3510 if ((data == NULL) || (data_len == 0) ||
3511 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003512 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513 return -EINVAL;
3514 }
3515
3516 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3517 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003518 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 return -EINVAL;
3520 }
3521
3522 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303523 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003524 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3526 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003527 true,
3528 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303529 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3530 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3532 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3533 return 0;
3534}
3535
3536/**
3537 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3538 * @wiphy: pointer to wireless wiphy structure.
3539 * @wdev: pointer to wireless_dev structure.
3540 * @data: Pointer to the Key data
3541 * @data_len:Length of the data passed
3542 *
3543 * This is called when wlan driver needs to save the keys received via
3544 * vendor specific command.
3545 *
3546 * Return: Return the Success or Failure code.
3547 */
3548static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3549 struct wireless_dev *wdev,
3550 const void *data, int data_len)
3551{
3552 int ret;
3553
3554 cds_ssr_protect(__func__);
3555 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3556 cds_ssr_unprotect(__func__);
3557
3558 return ret;
3559}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003560#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561
3562static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3563 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3564 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3565 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003566 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567};
3568
3569/**
3570 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3571 * @wiphy: pointer to wireless wiphy structure.
3572 * @wdev: pointer to wireless_dev structure.
3573 * @data: Pointer to the data to be passed via vendor interface
3574 * @data_len:Length of the data to be passed
3575 *
3576 * This is called when wlan driver needs to send wifi driver related info
3577 * (driver/fw version) to the user space application upon request.
3578 *
3579 * Return: Return the Success or Failure code.
3580 */
3581static int
3582__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3583 struct wireless_dev *wdev,
3584 const void *data, int data_len)
3585{
3586 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3587 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003588 tSirVersionString driver_version;
3589 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003592 struct sk_buff *reply_skb;
3593 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594
Jeff Johnson1f61b612016-02-12 16:28:33 -08003595 ENTER_DEV(wdev->netdev);
3596
Anurag Chouhan6d760662016-02-20 16:05:43 +05303597 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 hdd_err("Command not allowed in FTM mode");
3599 return -EPERM;
3600 }
3601
3602 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303603 if (status)
3604 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605
3606 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3607 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003608 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 return -EINVAL;
3610 }
3611
3612 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003613 hdd_err("Rcvd req for Driver version");
3614 strlcpy(driver_version, QWLAN_VERSIONSTR,
3615 sizeof(driver_version));
3616 skb_len += strlen(driver_version) + 1;
3617 count++;
3618 }
3619
3620 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3621 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3623 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003624 snprintf(firmware_version, sizeof(firmware_version),
3625 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3626 skb_len += strlen(firmware_version) + 1;
3627 count++;
3628 }
3629
3630 if (count == 0) {
3631 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 return -EINVAL;
3633 }
3634
Ryan Hsu7ac88852016-04-28 10:20:34 -07003635 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3636 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003639 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640 return -ENOMEM;
3641 }
3642
Ryan Hsu7ac88852016-04-28 10:20:34 -07003643 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3644 if (nla_put_string(reply_skb,
3645 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3646 driver_version))
3647 goto error_nla_fail;
3648 }
3649
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303650 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003651 if (nla_put_string(reply_skb,
3652 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3653 firmware_version))
3654 goto error_nla_fail;
3655 }
3656
3657 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3658 if (nla_put_u32(reply_skb,
3659 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3660 hdd_ctx->radio_index))
3661 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 }
3663
3664 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003665
3666error_nla_fail:
3667 hdd_err("nla put fail");
3668 kfree_skb(reply_skb);
3669 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670}
3671
3672/**
3673 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3674 * @wiphy: pointer to wireless wiphy structure.
3675 * @wdev: pointer to wireless_dev structure.
3676 * @data: Pointer to the data to be passed via vendor interface
3677 * @data_len:Length of the data to be passed
3678 *
3679 * This is called when wlan driver needs to send wifi driver related info
3680 * (driver/fw version) to the user space application upon request.
3681 *
3682 * Return: Return the Success or Failure code.
3683 */
3684static int
3685wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3686 struct wireless_dev *wdev,
3687 const void *data, int data_len)
3688{
3689 int ret;
3690
3691 cds_ssr_protect(__func__);
3692 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3693 cds_ssr_unprotect(__func__);
3694
3695 return ret;
3696}
3697
3698/**
3699 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3700 * @wiphy: pointer to wireless wiphy structure.
3701 * @wdev: pointer to wireless_dev structure.
3702 * @data: Pointer to the data to be passed via vendor interface
3703 * @data_len:Length of the data to be passed
3704 *
3705 * This is called by userspace to know the supported logger features
3706 *
3707 * Return: Return the Success or Failure code.
3708 */
3709static int
3710__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3711 struct wireless_dev *wdev,
3712 const void *data, int data_len)
3713{
3714 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3715 int status;
3716 uint32_t features;
3717 struct sk_buff *reply_skb = NULL;
3718
Jeff Johnson1f61b612016-02-12 16:28:33 -08003719 ENTER_DEV(wdev->netdev);
3720
Anurag Chouhan6d760662016-02-20 16:05:43 +05303721 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003722 hdd_err("Command not allowed in FTM mode");
3723 return -EPERM;
3724 }
3725
3726 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303727 if (status)
3728 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729
3730 features = 0;
3731
3732 if (hdd_is_memdump_supported())
3733 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3734 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3735 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3736 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3737
3738 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3739 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3740 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003741 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 return -ENOMEM;
3743 }
3744
Jeff Johnson020db452016-06-29 14:37:26 -07003745 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3747 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003748 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 kfree_skb(reply_skb);
3750 return -EINVAL;
3751 }
3752
3753 return cfg80211_vendor_cmd_reply(reply_skb);
3754}
3755
3756/**
3757 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3758 * @wiphy: pointer to wireless wiphy structure.
3759 * @wdev: pointer to wireless_dev structure.
3760 * @data: Pointer to the data to be passed via vendor interface
3761 * @data_len:Length of the data to be passed
3762 *
3763 * This is called by userspace to know the supported logger features
3764 *
3765 * Return: Return the Success or Failure code.
3766 */
3767static int
3768wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3769 struct wireless_dev *wdev,
3770 const void *data, int data_len)
3771{
3772 int ret;
3773
3774 cds_ssr_protect(__func__);
3775 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3776 data, data_len);
3777 cds_ssr_unprotect(__func__);
3778
3779 return ret;
3780}
3781
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003782#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783/**
3784 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3785 * @hdd_ctx_ptr: pointer to HDD Context.
3786 * @bssid: pointer to bssid of roamed AP.
3787 * @req_rsn_ie: Pointer to request RSN IE
3788 * @req_rsn_len: Length of the request RSN IE
3789 * @rsp_rsn_ie: Pointer to response RSN IE
3790 * @rsp_rsn_len: Length of the response RSN IE
3791 * @roam_info_ptr: Pointer to the roaming related information
3792 *
3793 * This is called when wlan driver needs to send the roaming and
3794 * authorization information after roaming.
3795 *
3796 * The information that would be sent is the request RSN IE, response
3797 * RSN IE and BSSID of the newly roamed AP.
3798 *
3799 * If the Authorized status is authenticated, then additional parameters
3800 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3801 * supplicant.
3802 *
3803 * The supplicant upon receiving this event would ignore the legacy
3804 * cfg80211_roamed call and use the entire information from this event.
3805 * The cfg80211_roamed should still co-exist since the kernel will
3806 * make use of the parameters even if the supplicant ignores it.
3807 *
3808 * Return: Return the Success or Failure code.
3809 */
3810int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3811 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3812 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3813{
3814 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003815 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 ENTER();
3817
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303818 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003819 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003821 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003822 !roam_info_ptr->roamSynchInProgress)
3823 return 0;
3824
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3826 NULL,
3827 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3828 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3829 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003830 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3832 GFP_KERNEL);
3833
3834 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003835 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836 return -EINVAL;
3837 }
3838
3839 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3840 ETH_ALEN, bssid) ||
3841 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3842 req_rsn_len, req_rsn_ie) ||
3843 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3844 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003845 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846 goto nla_put_failure;
3847 }
Jeff Johnson020db452016-06-29 14:37:26 -07003848 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 if (roam_info_ptr->synchAuthStatus ==
3850 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003851 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003852 if (nla_put_u8(skb,
3853 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3854 hdd_err("nla put fail");
3855 goto nla_put_failure;
3856 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003857 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3858 /* if FT or CCKM connection: dont send replay counter */
3859 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3860 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3861 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3862 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3863 nla_put(skb,
3864 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3865 SIR_REPLAY_CTR_LEN,
3866 roam_info_ptr->replay_ctr)) {
3867 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003868 hdd_err("failed to send replay counter.");
3869 goto nla_put_failure;
3870 }
3871 if (nla_put(skb,
3872 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3873 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3874 nla_put(skb,
3875 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3876 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3877 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 goto nla_put_failure;
3879 }
3880 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003881 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3883 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003884 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 goto nla_put_failure;
3886 }
3887 }
3888
Jeff Johnson020db452016-06-29 14:37:26 -07003889 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003890 roam_info_ptr->subnet_change_status);
3891
3892 /*
3893 * Add subnet change status if subnet has changed
3894 * 0 = unchanged
3895 * 1 = changed
3896 * 2 = unknown
3897 */
3898 if (roam_info_ptr->subnet_change_status) {
3899 if (nla_put_u8(skb,
3900 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3901 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003902 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003903 goto nla_put_failure;
3904 }
3905 }
3906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 cfg80211_vendor_event(skb, GFP_KERNEL);
3908 return 0;
3909
3910nla_put_failure:
3911 kfree_skb(skb);
3912 return -EINVAL;
3913}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003914#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915
3916static const struct nla_policy
3917wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3918
3919 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3920 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3921 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303922 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303923 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3924 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003925 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3926 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3927 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3928 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3929 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303930 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003931};
3932
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303934 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3935 *
3936 * @adapter: Pointer to HDD adapter
3937 * @ie_data: Pointer to Scan IEs buffer
3938 * @ie_len: Length of Scan IEs
3939 *
3940 * Return: 0 on success; error number otherwise
3941 */
3942static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3943 uint8_t *ie_data, uint8_t ie_len)
3944{
3945 hdd_scaninfo_t *scan_info = NULL;
3946 scan_info = &adapter->scan_info;
3947
3948 if (scan_info->default_scan_ies) {
3949 qdf_mem_free(scan_info->default_scan_ies);
3950 scan_info->default_scan_ies = NULL;
3951 }
3952
3953 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3954 if (!scan_info->default_scan_ies)
3955 return -ENOMEM;
3956
3957 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3958 scan_info->default_scan_ies_len = ie_len;
3959 return 0;
3960}
3961
3962/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3964 * vendor command
3965 *
3966 * @wiphy: wiphy device pointer
3967 * @wdev: wireless device pointer
3968 * @data: Vendor command data buffer
3969 * @data_len: Buffer length
3970 *
3971 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3972 *
3973 * Return: Error code.
3974 */
3975static int
3976__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3977 struct wireless_dev *wdev,
3978 const void *data,
3979 int data_len)
3980{
3981 struct net_device *dev = wdev->netdev;
3982 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3983 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3985 int ret_val = 0;
3986 u32 modulated_dtim;
3987 u16 stats_avg_factor;
3988 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303989 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003990 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003991 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303992 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303993 int attr_len;
3994 int access_policy = 0;
3995 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3996 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303997 uint16_t scan_ie_len = 0;
3998 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303999 struct sir_set_tx_rx_aggregation_size request;
4000 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004001 uint8_t retry, delay;
4002 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304003 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304004
Jeff Johnson1f61b612016-02-12 16:28:33 -08004005 ENTER_DEV(dev);
4006
Anurag Chouhan6d760662016-02-20 16:05:43 +05304007 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 hdd_err("Command not allowed in FTM mode");
4009 return -EPERM;
4010 }
4011
4012 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304013 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015
4016 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4017 data, data_len,
4018 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004019 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 return -EINVAL;
4021 }
4022
Krunal Sonie3531942016-04-12 17:43:53 -07004023 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4024 ftm_capab = nla_get_u32(tb[
4025 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4026 hdd_ctx->config->fine_time_meas_cap =
4027 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4028 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304029 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004030 hdd_ctx->config->fine_time_meas_cap);
4031 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4032 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4033 hdd_ctx->config->fine_time_meas_cap);
4034 }
4035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4037 modulated_dtim = nla_get_u32(
4038 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4039
4040 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4041 adapter->sessionId,
4042 modulated_dtim);
4043
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304044 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 ret_val = -EPERM;
4046 }
4047
Kapil Gupta6213c012016-09-02 19:39:09 +05304048 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4049 qpower = nla_get_u8(
4050 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4051 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4052 ret_val = -EINVAL;
4053 }
4054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4056 stats_avg_factor = nla_get_u16(
4057 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4058 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4059 adapter->sessionId,
4060 stats_avg_factor);
4061
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304062 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 ret_val = -EPERM;
4064 }
4065
4066
4067 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4068 guard_time = nla_get_u32(
4069 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4070 status = sme_configure_guard_time(hdd_ctx->hHal,
4071 adapter->sessionId,
4072 guard_time);
4073
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304074 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 ret_val = -EPERM;
4076 }
4077
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304078 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4079 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4080 attr_len = nla_len(
4081 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4082 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4083 hdd_info("Invalid value. attr_len %d",
4084 attr_len);
4085 return -EINVAL;
4086 }
4087
4088 nla_memcpy(&vendor_ie,
4089 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4090 attr_len);
4091 vendor_ie_present = true;
4092 hdd_info("Access policy vendor ie present.attr_len %d",
4093 attr_len);
4094 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4095 &vendor_ie[0], attr_len);
4096 }
4097
4098 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4099 access_policy = (int) nla_get_u32(
4100 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4101 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4102 (access_policy >
4103 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4104 hdd_info("Invalid value. access_policy %d",
4105 access_policy);
4106 return -EINVAL;
4107 }
4108 access_policy_present = true;
4109 hdd_info("Access policy present. access_policy %d",
4110 access_policy);
4111 }
4112
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004113 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4114 retry = nla_get_u8(tb[
4115 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4116 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4117 CFG_NON_AGG_RETRY_MAX : retry;
4118 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4119 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4120 retry, PDEV_CMD);
4121 }
4122
4123 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4124 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4125 retry = retry > CFG_AGG_RETRY_MAX ?
4126 CFG_AGG_RETRY_MAX : retry;
4127
4128 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4129 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4130 CFG_AGG_RETRY_MIN : retry;
4131 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4132 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4133 retry, PDEV_CMD);
4134 }
4135
4136 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4137 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4138 retry = retry > CFG_MGMT_RETRY_MAX ?
4139 CFG_MGMT_RETRY_MAX : retry;
4140 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4141 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4142 retry, PDEV_CMD);
4143 }
4144
4145 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4146 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4147 retry = retry > CFG_CTRL_RETRY_MAX ?
4148 CFG_CTRL_RETRY_MAX : retry;
4149 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4150 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4151 retry, PDEV_CMD);
4152 }
4153
4154 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4155 delay = nla_get_u8(tb[
4156 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4157 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4158 CFG_PROPAGATION_DELAY_MAX : delay;
4159 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4160 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4161 delay, PDEV_CMD);
4162 }
4163
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304164 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4165 tx_fail_count = nla_get_u32(
4166 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4167 if (tx_fail_count) {
4168 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4169 adapter->sessionId, tx_fail_count);
4170 if (QDF_STATUS_SUCCESS != status) {
4171 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4172 status);
4173 return -EINVAL;
4174 }
4175 }
4176 }
4177
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304178 if (vendor_ie_present && access_policy_present) {
4179 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4180 access_policy =
4181 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304182 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304183 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304184 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304185
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304186 hdd_info("calling sme_update_access_policy_vendor_ie");
4187 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4188 adapter->sessionId, &vendor_ie[0],
4189 access_policy);
4190 if (QDF_STATUS_SUCCESS != status) {
4191 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304192 return -EINVAL;
4193 }
4194 }
4195
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304196 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4197 set_value = nla_get_u8(
4198 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4199 hdd_info("set_value: %d", set_value);
4200 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4201 }
4202
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304203 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4204 scan_ie_len = nla_len(
4205 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4206 hdd_info("Received default scan IE of len %d session %d device mode %d",
4207 scan_ie_len, adapter->sessionId,
4208 adapter->device_mode);
4209 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4210 scan_ie = (uint8_t *) nla_data(tb
4211 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304212
4213 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4214 scan_ie_len))
4215 hdd_err("Failed to save default scan IEs");
4216
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304217 if (adapter->device_mode == QDF_STA_MODE) {
4218 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4219 adapter->sessionId, scan_ie,
4220 scan_ie_len);
4221 if (QDF_STATUS_SUCCESS != status)
4222 ret_val = -EPERM;
4223 }
4224 } else
4225 ret_val = -EPERM;
4226 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304227
4228 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4229 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4230 /* if one is specified, both must be specified */
4231 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4232 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4233 hdd_err("Both TX and RX MPDU Aggregation required");
4234 return -EINVAL;
4235 }
4236
4237 request.tx_aggregation_size = nla_get_u8(
4238 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4239 request.rx_aggregation_size = nla_get_u8(
4240 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4241 request.vdev_id = adapter->sessionId;
4242
4243 if (request.tx_aggregation_size >=
4244 CFG_TX_AGGREGATION_SIZE_MIN &&
4245 request.tx_aggregation_size <=
4246 CFG_TX_AGGREGATION_SIZE_MAX &&
4247 request.rx_aggregation_size >=
4248 CFG_RX_AGGREGATION_SIZE_MIN &&
4249 request.rx_aggregation_size <=
4250 CFG_RX_AGGREGATION_SIZE_MAX) {
4251 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4252 if (qdf_status != QDF_STATUS_SUCCESS) {
4253 hdd_err("failed to set aggr sizes err %d",
4254 qdf_status);
4255 ret_val = -EPERM;
4256 }
4257 } else {
4258 hdd_err("TX %d RX %d MPDU aggr size not in range",
4259 request.tx_aggregation_size,
4260 request.rx_aggregation_size);
4261 ret_val = -EINVAL;
4262 }
4263 }
4264
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304265 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4266 uint8_t ignore_assoc_disallowed;
4267
4268 ignore_assoc_disallowed
4269 = nla_get_u8(tb[
4270 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4271 hdd_info("Set ignore_assoc_disallowed value - %d",
4272 ignore_assoc_disallowed);
4273 if ((ignore_assoc_disallowed <
4274 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4275 (ignore_assoc_disallowed >
4276 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4277 return -EPERM;
4278
4279 sme_update_session_param(hdd_ctx->hHal,
4280 adapter->sessionId,
4281 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4282 ignore_assoc_disallowed);
4283 }
4284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 return ret_val;
4286}
4287
4288/**
4289 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4290 * vendor command
4291 *
4292 * @wiphy: wiphy device pointer
4293 * @wdev: wireless device pointer
4294 * @data: Vendor command data buffer
4295 * @data_len: Buffer length
4296 *
4297 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4298 *
4299 * Return: EOK or other error codes.
4300 */
4301static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4302 struct wireless_dev *wdev,
4303 const void *data,
4304 int data_len)
4305{
4306 int ret;
4307
4308 cds_ssr_protect(__func__);
4309 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4310 data, data_len);
4311 cds_ssr_unprotect(__func__);
4312
4313 return ret;
4314}
4315
4316static const struct
4317nla_policy
4318qca_wlan_vendor_wifi_logger_start_policy
4319[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4320 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4321 = {.type = NLA_U32 },
4322 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4323 = {.type = NLA_U32 },
4324 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4325 = {.type = NLA_U32 },
4326};
4327
4328/**
4329 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4330 * or disable the collection of packet statistics from the firmware
4331 * @wiphy: WIPHY structure pointer
4332 * @wdev: Wireless device structure pointer
4333 * @data: Pointer to the data received
4334 * @data_len: Length of the data received
4335 *
4336 * This function enables or disables the collection of packet statistics from
4337 * the firmware
4338 *
4339 * Return: 0 on success and errno on failure
4340 */
4341static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4342 struct wireless_dev *wdev,
4343 const void *data,
4344 int data_len)
4345{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304346 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4348 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4349 struct sir_wifi_start_log start_log;
4350
Jeff Johnson1f61b612016-02-12 16:28:33 -08004351 ENTER_DEV(wdev->netdev);
4352
Anurag Chouhan6d760662016-02-20 16:05:43 +05304353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 hdd_err("Command not allowed in FTM mode");
4355 return -EPERM;
4356 }
4357
4358 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304359 if (status)
4360 return status;
4361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362
4363 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4364 data, data_len,
4365 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004366 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 return -EINVAL;
4368 }
4369
4370 /* Parse and fetch ring id */
4371 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004372 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 return -EINVAL;
4374 }
4375 start_log.ring_id = nla_get_u32(
4376 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004377 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378
4379 /* Parse and fetch verbose level */
4380 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004381 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 return -EINVAL;
4383 }
4384 start_log.verbose_level = nla_get_u32(
4385 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004386 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387
4388 /* Parse and fetch flag */
4389 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004390 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 return -EINVAL;
4392 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304393 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304395 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304397 /* size is buff size which can be set using iwpriv command*/
4398 start_log.size = 0;
4399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4401
4402 if (start_log.ring_id == RING_ID_WAKELOCK) {
4403 /* Start/stop wakelock events */
4404 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4405 cds_set_wakelock_logging(true);
4406 else
4407 cds_set_wakelock_logging(false);
4408 return 0;
4409 }
4410
4411 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304412 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004413 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414 status);
4415 return -EINVAL;
4416 }
4417 return 0;
4418}
4419
4420/**
4421 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4422 * or disable the collection of packet statistics from the firmware
4423 * @wiphy: WIPHY structure pointer
4424 * @wdev: Wireless device structure pointer
4425 * @data: Pointer to the data received
4426 * @data_len: Length of the data received
4427 *
4428 * This function is used to enable or disable the collection of packet
4429 * statistics from the firmware
4430 *
4431 * Return: 0 on success and errno on failure
4432 */
4433static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4434 struct wireless_dev *wdev,
4435 const void *data,
4436 int data_len)
4437{
4438 int ret = 0;
4439
4440 cds_ssr_protect(__func__);
4441 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4442 wdev, data, data_len);
4443 cds_ssr_unprotect(__func__);
4444
4445 return ret;
4446}
4447
4448static const struct
4449nla_policy
4450qca_wlan_vendor_wifi_logger_get_ring_data_policy
4451[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4452 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4453 = {.type = NLA_U32 },
4454};
4455
4456/**
4457 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4458 * @wiphy: WIPHY structure pointer
4459 * @wdev: Wireless device structure pointer
4460 * @data: Pointer to the data received
4461 * @data_len: Length of the data received
4462 *
4463 * This function is used to flush or retrieve the per packet statistics from
4464 * the driver
4465 *
4466 * Return: 0 on success and errno on failure
4467 */
4468static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4469 struct wireless_dev *wdev,
4470 const void *data,
4471 int data_len)
4472{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304473 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 uint32_t ring_id;
4475 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4476 struct nlattr *tb
4477 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4478
Jeff Johnson1f61b612016-02-12 16:28:33 -08004479 ENTER_DEV(wdev->netdev);
4480
Anurag Chouhan6d760662016-02-20 16:05:43 +05304481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 hdd_err("Command not allowed in FTM mode");
4483 return -EPERM;
4484 }
4485
4486 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304487 if (status)
4488 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489
4490 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4491 data, data_len,
4492 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004493 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 return -EINVAL;
4495 }
4496
4497 /* Parse and fetch ring id */
4498 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004499 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 return -EINVAL;
4501 }
4502
4503 ring_id = nla_get_u32(
4504 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4505
4506 if (ring_id == RING_ID_PER_PACKET_STATS) {
4507 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004508 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304509 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4510 /*
4511 * As part of DRIVER ring ID, flush both driver and fw logs.
4512 * For other Ring ID's driver doesn't have any rings to flush
4513 */
4514 hdd_notice("Bug report triggered by framework");
4515
4516 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4517 WLAN_LOG_INDICATOR_FRAMEWORK,
4518 WLAN_LOG_REASON_CODE_UNUSED,
4519 true, false);
4520 if (QDF_STATUS_SUCCESS != status) {
4521 hdd_err("Failed to trigger bug report");
4522 return -EINVAL;
4523 }
4524 } else {
4525 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4526 WLAN_LOG_INDICATOR_FRAMEWORK,
4527 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 return 0;
4530}
4531
4532/**
4533 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4534 * @wiphy: WIPHY structure pointer
4535 * @wdev: Wireless device structure pointer
4536 * @data: Pointer to the data received
4537 * @data_len: Length of the data received
4538 *
4539 * This function is used to flush or retrieve the per packet statistics from
4540 * the driver
4541 *
4542 * Return: 0 on success and errno on failure
4543 */
4544static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4545 struct wireless_dev *wdev,
4546 const void *data,
4547 int data_len)
4548{
4549 int ret = 0;
4550
4551 cds_ssr_protect(__func__);
4552 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4553 wdev, data, data_len);
4554 cds_ssr_unprotect(__func__);
4555
4556 return ret;
4557}
4558
4559#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4560/**
4561 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4562 * @hdd_ctx: HDD context
4563 * @request_id: [input] request id
4564 * @pattern_id: [output] pattern id
4565 *
4566 * This function loops through request id to pattern id array
4567 * if the slot is available, store the request id and return pattern id
4568 * if entry exists, return the pattern id
4569 *
4570 * Return: 0 on success and errno on failure
4571 */
4572static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4573 uint32_t request_id,
4574 uint8_t *pattern_id)
4575{
4576 uint32_t i;
4577
4578 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4579 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4580 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4581 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4582 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4583 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4584 return 0;
4585 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4586 request_id) {
4587 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4588 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4589 return 0;
4590 }
4591 }
4592 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4593 return -EINVAL;
4594}
4595
4596/**
4597 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4598 * @hdd_ctx: HDD context
4599 * @request_id: [input] request id
4600 * @pattern_id: [output] pattern id
4601 *
4602 * This function loops through request id to pattern id array
4603 * reset request id to 0 (slot available again) and
4604 * return pattern id
4605 *
4606 * Return: 0 on success and errno on failure
4607 */
4608static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4609 uint32_t request_id,
4610 uint8_t *pattern_id)
4611{
4612 uint32_t i;
4613
4614 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4615 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4616 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4617 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4618 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4619 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4620 return 0;
4621 }
4622 }
4623 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4624 return -EINVAL;
4625}
4626
4627
4628/*
4629 * define short names for the global vendor params
4630 * used by __wlan_hdd_cfg80211_offloaded_packets()
4631 */
4632#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4633#define PARAM_REQUEST_ID \
4634 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4635#define PARAM_CONTROL \
4636 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4637#define PARAM_IP_PACKET \
4638 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4639#define PARAM_SRC_MAC_ADDR \
4640 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4641#define PARAM_DST_MAC_ADDR \
4642 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4643#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4644
4645/**
4646 * wlan_hdd_add_tx_ptrn() - add tx pattern
4647 * @adapter: adapter pointer
4648 * @hdd_ctx: hdd context
4649 * @tb: nl attributes
4650 *
4651 * This function reads the NL attributes and forms a AddTxPtrn message
4652 * posts it to SME.
4653 *
4654 */
4655static int
4656wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4657 struct nlattr **tb)
4658{
4659 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304660 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661 uint32_t request_id, ret, len;
4662 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304663 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 uint16_t eth_type = htons(ETH_P_IP);
4665
4666 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004667 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 return -ENOTSUPP;
4669 }
4670
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304671 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 return -ENOMEM;
4675 }
4676
4677 /* Parse and fetch request Id */
4678 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004679 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 goto fail;
4681 }
4682
4683 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4684 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004685 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 return -EINVAL;
4687 }
Jeff Johnson77848112016-06-29 14:52:06 -07004688 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
4690 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004691 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 goto fail;
4693 }
4694 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004695 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004697 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698 goto fail;
4699 }
4700
4701 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004702 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 goto fail;
4704 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004705 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304706 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004707 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004708 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709
Anurag Chouhanc5548422016-02-24 18:33:27 +05304710 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004711 &adapter->macAddressCurrent)) {
4712 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 goto fail;
4714 }
4715
4716 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004717 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718 goto fail;
4719 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304720 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004721 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 MAC_ADDR_ARRAY(dst_addr.bytes));
4723
4724 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004725 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 goto fail;
4727 }
4728 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004729 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730
4731 if (add_req->ucPtrnSize < 0 ||
4732 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4733 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004734 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004735 add_req->ucPtrnSize);
4736 goto fail;
4737 }
4738
4739 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304740 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304741 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304742 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304743 QDF_MAC_ADDR_SIZE);
4744 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304745 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 len += 2;
4747
4748 /*
4749 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4750 * ------------------------------------------------------------
4751 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4752 * ------------------------------------------------------------
4753 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304754 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 nla_data(tb[PARAM_IP_PACKET]),
4756 add_req->ucPtrnSize);
4757 add_req->ucPtrnSize += len;
4758
4759 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4760 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004761 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 goto fail;
4763 }
4764 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004765 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766
4767 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304768 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004769 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 goto fail;
4771 }
4772
4773 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304774 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775 return 0;
4776
4777fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304778 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 return -EINVAL;
4780}
4781
4782/**
4783 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4784 * @adapter: adapter pointer
4785 * @hdd_ctx: hdd context
4786 * @tb: nl attributes
4787 *
4788 * This function reads the NL attributes and forms a DelTxPtrn message
4789 * posts it to SME.
4790 *
4791 */
4792static int
4793wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4794 struct nlattr **tb)
4795{
4796 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304797 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 uint32_t request_id, ret;
4799 uint8_t pattern_id = 0;
4800
4801 /* Parse and fetch request Id */
4802 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004803 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 return -EINVAL;
4805 }
4806 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4807 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004808 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 return -EINVAL;
4810 }
4811
4812 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4813 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004814 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 return -EINVAL;
4816 }
4817
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304818 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004820 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 return -ENOMEM;
4822 }
4823
Anurag Chouhanc5548422016-02-24 18:33:27 +05304824 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004825 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004827 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004828 request_id, del_req->ucPtrnId);
4829
4830 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304831 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004832 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 goto fail;
4834 }
4835
4836 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304837 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 return 0;
4839
4840fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304841 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842 return -EINVAL;
4843}
4844
4845
4846/**
4847 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4848 * @wiphy: Pointer to wireless phy
4849 * @wdev: Pointer to wireless device
4850 * @data: Pointer to data
4851 * @data_len: Data length
4852 *
4853 * Return: 0 on success, negative errno on failure
4854 */
4855static int
4856__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4857 struct wireless_dev *wdev,
4858 const void *data,
4859 int data_len)
4860{
4861 struct net_device *dev = wdev->netdev;
4862 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4863 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4864 struct nlattr *tb[PARAM_MAX + 1];
4865 uint8_t control;
4866 int ret;
4867 static const struct nla_policy policy[PARAM_MAX + 1] = {
4868 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4869 [PARAM_CONTROL] = { .type = NLA_U32 },
4870 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304871 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304873 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874 [PARAM_PERIOD] = { .type = NLA_U32 },
4875 };
4876
Jeff Johnson1f61b612016-02-12 16:28:33 -08004877 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878
Anurag Chouhan6d760662016-02-20 16:05:43 +05304879 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 hdd_err("Command not allowed in FTM mode");
4881 return -EPERM;
4882 }
4883
4884 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304885 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887
4888 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 return -ENOTSUPP;
4891 }
4892
4893 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004894 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 return -EINVAL;
4896 }
4897
4898 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004899 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900 return -EINVAL;
4901 }
4902 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004903 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904
4905 if (control == WLAN_START_OFFLOADED_PACKETS)
4906 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4907 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4908 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4909 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913}
4914
4915/*
4916 * done with short names for the global vendor params
4917 * used by __wlan_hdd_cfg80211_offloaded_packets()
4918 */
4919#undef PARAM_MAX
4920#undef PARAM_REQUEST_ID
4921#undef PARAM_CONTROL
4922#undef PARAM_IP_PACKET
4923#undef PARAM_SRC_MAC_ADDR
4924#undef PARAM_DST_MAC_ADDR
4925#undef PARAM_PERIOD
4926
4927/**
4928 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
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 wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4937 struct wireless_dev *wdev,
4938 const void *data,
4939 int data_len)
4940{
4941 int ret = 0;
4942
4943 cds_ssr_protect(__func__);
4944 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4945 wdev, data, data_len);
4946 cds_ssr_unprotect(__func__);
4947
4948 return ret;
4949}
4950#endif
4951
4952/*
4953 * define short names for the global vendor params
4954 * used by __wlan_hdd_cfg80211_monitor_rssi()
4955 */
4956#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4957#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4958#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4959#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4960#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4961
4962/**
4963 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4964 * @wiphy: Pointer to wireless phy
4965 * @wdev: Pointer to wireless device
4966 * @data: Pointer to data
4967 * @data_len: Data length
4968 *
4969 * Return: 0 on success, negative errno on failure
4970 */
4971static int
4972__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4973 struct wireless_dev *wdev,
4974 const void *data,
4975 int data_len)
4976{
4977 struct net_device *dev = wdev->netdev;
4978 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4979 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4980 struct nlattr *tb[PARAM_MAX + 1];
4981 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304982 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983 int ret;
4984 uint32_t control;
4985 static const struct nla_policy policy[PARAM_MAX + 1] = {
4986 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4987 [PARAM_CONTROL] = { .type = NLA_U32 },
4988 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4989 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4990 };
4991
Jeff Johnson1f61b612016-02-12 16:28:33 -08004992 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05304994 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
4995 hdd_err("invalid session id: %d", adapter->sessionId);
4996 return -EINVAL;
4997 }
4998
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305000 if (ret)
5001 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002
5003 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005004 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return -ENOTSUPP;
5006 }
5007
5008 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005009 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010 return -EINVAL;
5011 }
5012
5013 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005014 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005015 return -EINVAL;
5016 }
5017
5018 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005019 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 return -EINVAL;
5021 }
5022
5023 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5024 req.session_id = adapter->sessionId;
5025 control = nla_get_u32(tb[PARAM_CONTROL]);
5026
5027 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5028 req.control = true;
5029 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005030 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 return -EINVAL;
5032 }
5033
5034 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005035 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 return -EINVAL;
5037 }
5038
5039 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5040 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5041
5042 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005043 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005044 req.min_rssi, req.max_rssi);
5045 return -EINVAL;
5046 }
Jeff Johnson77848112016-06-29 14:52:06 -07005047 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 req.min_rssi, req.max_rssi);
5049
5050 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5051 req.control = false;
5052 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005053 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005054 return -EINVAL;
5055 }
Jeff Johnson77848112016-06-29 14:52:06 -07005056 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 req.request_id, req.session_id, req.control);
5058
5059 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305060 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005061 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 return -EINVAL;
5063 }
5064
5065 return 0;
5066}
5067
5068/*
5069 * done with short names for the global vendor params
5070 * used by __wlan_hdd_cfg80211_monitor_rssi()
5071 */
5072#undef PARAM_MAX
5073#undef PARAM_CONTROL
5074#undef PARAM_REQUEST_ID
5075#undef PARAM_MAX_RSSI
5076#undef PARAM_MIN_RSSI
5077
5078/**
5079 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5080 * @wiphy: wiphy structure pointer
5081 * @wdev: Wireless device structure pointer
5082 * @data: Pointer to the data received
5083 * @data_len: Length of @data
5084 *
5085 * Return: 0 on success; errno on failure
5086 */
5087static int
5088wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5089 const void *data, int data_len)
5090{
5091 int ret;
5092
5093 cds_ssr_protect(__func__);
5094 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5095 cds_ssr_unprotect(__func__);
5096
5097 return ret;
5098}
5099
5100/**
5101 * hdd_rssi_threshold_breached() - rssi breached NL event
5102 * @hddctx: HDD context
5103 * @data: rssi breached event data
5104 *
5105 * This function reads the rssi breached event %data and fill in the skb with
5106 * NL attributes and send up the NL event.
5107 *
5108 * Return: none
5109 */
5110void hdd_rssi_threshold_breached(void *hddctx,
5111 struct rssi_breach_event *data)
5112{
5113 hdd_context_t *hdd_ctx = hddctx;
5114 struct sk_buff *skb;
5115
5116 ENTER();
5117
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305118 if (wlan_hdd_validate_context(hdd_ctx))
5119 return;
5120 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005121 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 return;
5123 }
5124
5125 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5126 NULL,
5127 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5128 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5129 GFP_KERNEL);
5130
5131 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005132 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133 return;
5134 }
5135
Jeff Johnson77848112016-06-29 14:52:06 -07005136 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005138 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005139 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5140
5141 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5142 data->request_id) ||
5143 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5144 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5145 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5146 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005147 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 goto fail;
5149 }
5150
5151 cfg80211_vendor_event(skb, GFP_KERNEL);
5152 return;
5153
5154fail:
5155 kfree_skb(skb);
5156 return;
5157}
5158
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305159static const struct nla_policy
5160ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5161 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5162};
5163
5164/**
5165 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5166 * @wiphy: Pointer to wireless phy
5167 * @wdev: Pointer to wireless device
5168 * @data: Pointer to data
5169 * @data_len: Length of @data
5170 *
5171 * Return: 0 on success, negative errno on failure
5172 */
5173static int
5174__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5175 struct wireless_dev *wdev,
5176 const void *data, int data_len)
5177{
5178 int status;
5179 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5180 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005181 struct net_device *dev = wdev->netdev;
5182 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305183
5184 ENTER_DEV(wdev->netdev);
5185
5186 status = wlan_hdd_validate_context(pHddCtx);
5187 if (0 != status)
5188 return status;
5189 if (!pHddCtx->config->fhostNSOffload) {
5190 hdd_err("ND Offload not supported");
5191 return -EINVAL;
5192 }
5193
5194 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5195 (struct nlattr *)data,
5196 data_len, ns_offload_set_policy)) {
5197 hdd_err("nla_parse failed");
5198 return -EINVAL;
5199 }
5200
5201 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5202 hdd_err("ND Offload flag attribute not present");
5203 return -EINVAL;
5204 }
5205
5206 pHddCtx->ns_offload_enable =
5207 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5208
Dustin Brownd8279d22016-09-07 14:52:57 -07005209 /* update ns offload in case it is already enabled/disabled */
5210 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5211
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305212 return 0;
5213}
5214
5215/**
5216 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5217 * @wiphy: pointer to wireless wiphy structure.
5218 * @wdev: pointer to wireless_dev structure.
5219 * @data: Pointer to the data to be passed via vendor interface
5220 * @data_len:Length of the data to be passed
5221 *
5222 * Return: Return the Success or Failure code.
5223 */
5224static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5225 struct wireless_dev *wdev,
5226 const void *data, int data_len)
5227{
5228 int ret;
5229
5230 cds_ssr_protect(__func__);
5231 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5232 cds_ssr_unprotect(__func__);
5233
5234 return ret;
5235}
5236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5238 * @wiphy: Pointer to wireless phy
5239 * @wdev: Pointer to wireless device
5240 * @data: Pointer to data
5241 * @data_len: Data length
5242 *
5243 * This function return the preferred frequency list generated by the policy
5244 * manager.
5245 *
5246 * Return: success or failure code
5247 */
5248static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5249 struct wireless_dev
5250 *wdev, const void *data,
5251 int data_len)
5252{
5253 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5254 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305255 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305256 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305258 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 enum cds_con_mode intf_mode;
5260 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5261 struct sk_buff *reply_skb;
5262
Jeff Johnson1f61b612016-02-12 16:28:33 -08005263 ENTER_DEV(wdev->netdev);
5264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265 ret = wlan_hdd_validate_context(hdd_ctx);
5266 if (ret)
5267 return -EINVAL;
5268
5269 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5270 data, data_len, NULL)) {
5271 hdd_err("Invalid ATTR");
5272 return -EINVAL;
5273 }
5274
5275 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5276 hdd_err("attr interface type failed");
5277 return -EINVAL;
5278 }
5279
5280 intf_mode = nla_get_u32(tb
5281 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5282
5283 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5284 hdd_err("Invalid interface type");
5285 return -EINVAL;
5286 }
5287
5288 hdd_debug("Userspace requested pref freq list");
5289
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305290 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5291 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305292 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 hdd_err("Get pcl failed");
5294 return -EINVAL;
5295 }
5296
5297 /* convert channel number to frequency */
5298 for (i = 0; i < pcl_len; i++) {
5299 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5300 freq_list[i] =
5301 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005302 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 else
5304 freq_list[i] =
5305 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005306 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 }
5308
5309 /* send the freq_list back to supplicant */
5310 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5311 sizeof(u32) *
5312 pcl_len +
5313 NLMSG_HDRLEN);
5314
5315 if (!reply_skb) {
5316 hdd_err("Allocate reply_skb failed");
5317 return -EINVAL;
5318 }
5319
5320 if (nla_put_u32(reply_skb,
5321 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5322 intf_mode) ||
5323 nla_put(reply_skb,
5324 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5325 sizeof(uint32_t) * pcl_len,
5326 freq_list)) {
5327 hdd_err("nla put fail");
5328 kfree_skb(reply_skb);
5329 return -EINVAL;
5330 }
5331
5332 return cfg80211_vendor_cmd_reply(reply_skb);
5333}
5334
5335/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5336 * @wiphy: Pointer to wireless phy
5337 * @wdev: Pointer to wireless device
5338 * @data: Pointer to data
5339 * @data_len: Data length
5340 *
5341 * This function return the preferred frequency list generated by the policy
5342 * manager.
5343 *
5344 * Return: success or failure code
5345 */
5346static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5347 struct wireless_dev
5348 *wdev, const void *data,
5349 int data_len)
5350{
5351 int ret = 0;
5352
5353 cds_ssr_protect(__func__);
5354 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5355 data, data_len);
5356 cds_ssr_unprotect(__func__);
5357
5358 return ret;
5359}
5360
5361/**
5362 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5363 * @wiphy: Pointer to wireless phy
5364 * @wdev: Pointer to wireless device
5365 * @data: Pointer to data
5366 * @data_len: Data length
5367 *
5368 * Return: 0 on success, negative errno on failure
5369 */
5370static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5371 struct wireless_dev *wdev,
5372 const void *data,
5373 int data_len)
5374{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305375 struct net_device *ndev = wdev->netdev;
5376 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5378 int ret = 0;
5379 enum cds_con_mode intf_mode;
5380 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5381 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382
Jeff Johnson1f61b612016-02-12 16:28:33 -08005383 ENTER_DEV(ndev);
5384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 ret = wlan_hdd_validate_context(hdd_ctx);
5386 if (ret)
5387 return ret;
5388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5390 data, data_len, NULL)) {
5391 hdd_err("Invalid ATTR");
5392 return -EINVAL;
5393 }
5394
5395 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5396 hdd_err("attr interface type failed");
5397 return -EINVAL;
5398 }
5399
5400 intf_mode = nla_get_u32(tb
5401 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5402
5403 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5404 hdd_err("Invalid interface type");
5405 return -EINVAL;
5406 }
5407
5408 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5409 hdd_err("attr probable freq failed");
5410 return -EINVAL;
5411 }
5412
5413 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5414 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5415
5416 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005417 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 channel_hint, HW_MODE_20_MHZ)) {
5419 hdd_err("Set channel hint failed due to concurrency check");
5420 return -EINVAL;
5421 }
5422
Krunal Soni09e55032016-06-07 10:06:55 -07005423 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5424 hdd_warn("Remain On Channel Pending");
5425
Krunal Soni3091bcc2016-06-23 12:28:21 -07005426 ret = qdf_reset_connection_update();
5427 if (!QDF_IS_STATUS_SUCCESS(ret))
5428 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429
Krunal Soni3091bcc2016-06-23 12:28:21 -07005430 ret = cds_current_connections_update(adapter->sessionId,
5431 channel_hint,
5432 SIR_UPDATE_REASON_SET_OPER_CHAN);
5433 if (QDF_STATUS_E_FAILURE == ret) {
5434 /* return in the failure case */
5435 hdd_err("ERROR: connections update failed!!");
5436 return -EINVAL;
5437 }
5438
5439 if (QDF_STATUS_SUCCESS == ret) {
5440 /*
5441 * Success is the only case for which we expect hw mode
5442 * change to take place, hence we need to wait.
5443 * For any other return value it should be a pass
5444 * through
5445 */
5446 ret = qdf_wait_for_connection_update();
5447 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5448 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 return -EINVAL;
5450 }
5451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 }
5453
5454 return 0;
5455}
5456
5457/**
5458 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5459 * @wiphy: Pointer to wireless phy
5460 * @wdev: Pointer to wireless device
5461 * @data: Pointer to data
5462 * @data_len: Data length
5463 *
5464 * Return: 0 on success, negative errno on failure
5465 */
5466static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5467 struct wireless_dev *wdev,
5468 const void *data,
5469 int data_len)
5470{
5471 int ret = 0;
5472
5473 cds_ssr_protect(__func__);
5474 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5475 data, data_len);
5476 cds_ssr_unprotect(__func__);
5477
5478 return ret;
5479}
5480
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305481static const struct
5482nla_policy
5483qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5484 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5485};
5486
5487/**
5488 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5489 * @wiphy: WIPHY structure pointer
5490 * @wdev: Wireless device structure pointer
5491 * @data: Pointer to the data received
5492 * @data_len: Length of the data received
5493 *
5494 * This function is used to get link properties like nss, rate flags and
5495 * operating frequency for the active connection with the given peer.
5496 *
5497 * Return: 0 on success and errno on failure
5498 */
5499static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5500 struct wireless_dev *wdev,
5501 const void *data,
5502 int data_len)
5503{
5504 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5505 struct net_device *dev = wdev->netdev;
5506 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5507 hdd_station_ctx_t *hdd_sta_ctx;
5508 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305509 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305510 uint32_t sta_id;
5511 struct sk_buff *reply_skb;
5512 uint32_t rate_flags = 0;
5513 uint8_t nss;
5514 uint8_t final_rate_flags = 0;
5515 uint32_t freq;
5516
Jeff Johnson1f61b612016-02-12 16:28:33 -08005517 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305518
Anurag Chouhan6d760662016-02-20 16:05:43 +05305519 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305520 hdd_err("Command not allowed in FTM mode");
5521 return -EPERM;
5522 }
5523
5524 if (0 != wlan_hdd_validate_context(hdd_ctx))
5525 return -EINVAL;
5526
5527 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5528 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005529 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305530 return -EINVAL;
5531 }
5532
5533 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005534 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305535 adapter->device_mode);
5536 return -EINVAL;
5537 }
5538
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305539 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305540 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005541 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305542 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5543
Krunal Sonib4326f22016-03-10 13:05:51 -08005544 if (adapter->device_mode == QDF_STA_MODE ||
5545 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305546 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5547 if ((hdd_sta_ctx->conn_info.connState !=
5548 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305549 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305550 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005551 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305552 MAC_ADDR_ARRAY(peer_mac));
5553 return -EINVAL;
5554 }
5555
5556 nss = hdd_sta_ctx->conn_info.nss;
5557 freq = cds_chan_to_freq(
5558 hdd_sta_ctx->conn_info.operationChannel);
5559 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005560 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5561 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305562
5563 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5564 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305565 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305566 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305567 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305568 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305569 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305570 break;
5571 }
5572
5573 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305575 MAC_ADDR_ARRAY(peer_mac));
5576 return -EINVAL;
5577 }
5578
5579 nss = adapter->aStaInfo[sta_id].nss;
5580 freq = cds_chan_to_freq(
5581 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5582 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5583 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005584 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305585 MAC_ADDR_ARRAY(peer_mac));
5586 return -EINVAL;
5587 }
5588
5589 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5590 if (rate_flags & eHAL_TX_RATE_VHT80) {
5591 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005592#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305593 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005594#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305595 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5596 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005597#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305598 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005599#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305600 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5601 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5602 } else if (rate_flags &
5603 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5604 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005605#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305606 if (rate_flags & eHAL_TX_RATE_HT40)
5607 final_rate_flags |=
5608 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005609#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305610 }
5611
5612 if (rate_flags & eHAL_TX_RATE_SGI) {
5613 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5614 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5615 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5616 }
5617 }
5618
5619 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5620 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5621
5622 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005623 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305624 return -EINVAL;
5625 }
5626
5627 if (nla_put_u8(reply_skb,
5628 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5629 nss) ||
5630 nla_put_u8(reply_skb,
5631 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5632 final_rate_flags) ||
5633 nla_put_u32(reply_skb,
5634 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5635 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005636 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305637 kfree_skb(reply_skb);
5638 return -EINVAL;
5639 }
5640
5641 return cfg80211_vendor_cmd_reply(reply_skb);
5642}
5643
5644/**
5645 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5646 * properties.
5647 * @wiphy: WIPHY structure pointer
5648 * @wdev: Wireless device structure pointer
5649 * @data: Pointer to the data received
5650 * @data_len: Length of the data received
5651 *
5652 * This function is used to get link properties like nss, rate flags and
5653 * operating frequency for the active connection with the given peer.
5654 *
5655 * Return: 0 on success and errno on failure
5656 */
5657static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5658 struct wireless_dev *wdev,
5659 const void *data,
5660 int data_len)
5661{
5662 int ret = 0;
5663
5664 cds_ssr_protect(__func__);
5665 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5666 wdev, data, data_len);
5667 cds_ssr_unprotect(__func__);
5668
5669 return ret;
5670}
5671
Peng Xu278d0122015-09-24 16:34:17 -07005672static const struct
5673nla_policy
5674qca_wlan_vendor_ota_test_policy
5675[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5676 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5677};
5678
5679/**
5680 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5681 * @wiphy: Pointer to wireless phy
5682 * @wdev: Pointer to wireless device
5683 * @data: Pointer to data
5684 * @data_len: Data length
5685 *
5686 * Return: 0 on success, negative errno on failure
5687 */
5688static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5689 struct wireless_dev *wdev,
5690 const void *data,
5691 int data_len)
5692{
5693 struct net_device *dev = wdev->netdev;
5694 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5695 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5696 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5697 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5698 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305699 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005700 uint32_t current_roam_state;
5701
Jeff Johnson1f61b612016-02-12 16:28:33 -08005702 ENTER_DEV(dev);
5703
Anurag Chouhan6d760662016-02-20 16:05:43 +05305704 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005705 hdd_err("Command not allowed in FTM mode");
5706 return -EPERM;
5707 }
5708
5709 if (0 != wlan_hdd_validate_context(hdd_ctx))
5710 return -EINVAL;
5711
5712 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5713 data, data_len,
5714 qca_wlan_vendor_ota_test_policy)) {
5715 hdd_err("invalid attr");
5716 return -EINVAL;
5717 }
5718
5719 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5720 hdd_err("attr ota test failed");
5721 return -EINVAL;
5722 }
5723
5724 ota_enable = nla_get_u8(
5725 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5726
5727 hdd_info(" OTA test enable = %d", ota_enable);
5728 if (ota_enable != 1) {
5729 hdd_err("Invalid value, only enable test mode is supported!");
5730 return -EINVAL;
5731 }
5732
5733 current_roam_state =
5734 sme_get_current_roam_state(hal, adapter->sessionId);
5735 status = sme_stop_roaming(hal, adapter->sessionId,
5736 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305737 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005738 hdd_err("Enable/Disable roaming failed");
5739 return -EINVAL;
5740 }
5741
5742 status = sme_ps_enable_disable(hal, adapter->sessionId,
5743 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305744 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005745 hdd_err("Enable/Disable power save failed");
5746 /* restore previous roaming setting */
5747 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5748 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5749 status = sme_start_roaming(hal, adapter->sessionId,
5750 eCsrHddIssued);
5751 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5752 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5753 status = sme_stop_roaming(hal, adapter->sessionId,
5754 eCsrHddIssued);
5755
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305756 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005757 hdd_err("Restoring roaming state failed");
5758
5759 return -EINVAL;
5760 }
5761
5762
5763 return 0;
5764}
5765
5766/**
5767 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5768 * @wiphy: Pointer to wireless phy
5769 * @wdev: Pointer to wireless device
5770 * @data: Pointer to data
5771 * @data_len: Data length
5772 *
5773 * Return: 0 on success, negative errno on failure
5774 */
5775static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5776 struct wireless_dev *wdev,
5777 const void *data,
5778 int data_len)
5779{
5780 int ret = 0;
5781
5782 cds_ssr_protect(__func__);
5783 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5784 cds_ssr_unprotect(__func__);
5785
5786 return ret;
5787}
5788
Peng Xu4d67c8f2015-10-16 16:02:26 -07005789/**
5790 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5791 * @wiphy: Pointer to wireless phy
5792 * @wdev: Pointer to wireless device
5793 * @data: Pointer to data
5794 * @data_len: Data length
5795 *
5796 * Return: 0 on success, negative errno on failure
5797 */
5798static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5799 struct wireless_dev *wdev,
5800 const void *data,
5801 int data_len)
5802{
5803 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5804 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005805 hdd_adapter_t *adapter;
5806 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005807 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5808 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005809 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005810
Jeff Johnson1f61b612016-02-12 16:28:33 -08005811 ENTER_DEV(dev);
5812
Peng Xu4d67c8f2015-10-16 16:02:26 -07005813 ret = wlan_hdd_validate_context(hdd_ctx);
5814 if (ret)
5815 return ret;
5816
5817 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5818
5819 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5820 data, data_len, NULL)) {
5821 hdd_err("Invalid ATTR");
5822 return -EINVAL;
5823 }
5824
5825 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5826 hdd_err("attr tx power scale failed");
5827 return -EINVAL;
5828 }
5829
5830 scale_value = nla_get_u8(tb
5831 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5832
5833 if (scale_value > MAX_TXPOWER_SCALE) {
5834 hdd_err("Invalid tx power scale level");
5835 return -EINVAL;
5836 }
5837
Peng Xu62c8c432016-05-09 15:23:02 -07005838 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005839
Peng Xu62c8c432016-05-09 15:23:02 -07005840 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005841 hdd_err("Set tx power scale failed");
5842 return -EINVAL;
5843 }
5844
5845 return 0;
5846}
5847
5848/**
5849 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5850 * @wiphy: Pointer to wireless phy
5851 * @wdev: Pointer to wireless device
5852 * @data: Pointer to data
5853 * @data_len: Data length
5854 *
5855 * Return: 0 on success, negative errno on failure
5856 */
5857static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5858 struct wireless_dev *wdev,
5859 const void *data,
5860 int data_len)
5861{
Peng Xu62c8c432016-05-09 15:23:02 -07005862 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005863
5864 cds_ssr_protect(__func__);
5865 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5866 data, data_len);
5867 cds_ssr_unprotect(__func__);
5868
5869 return ret;
5870}
5871
5872/**
5873 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5874 * @wiphy: Pointer to wireless phy
5875 * @wdev: Pointer to wireless device
5876 * @data: Pointer to data
5877 * @data_len: Data length
5878 *
5879 * Return: 0 on success, negative errno on failure
5880 */
5881static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5882 struct wireless_dev *wdev,
5883 const void *data,
5884 int data_len)
5885{
5886 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5887 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005888 hdd_adapter_t *adapter;
5889 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005890 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5891 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005892 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005893
Jeff Johnson1f61b612016-02-12 16:28:33 -08005894 ENTER_DEV(dev);
5895
Peng Xu4d67c8f2015-10-16 16:02:26 -07005896 ret = wlan_hdd_validate_context(hdd_ctx);
5897 if (ret)
5898 return ret;
5899
5900 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5901
5902 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5903 data, data_len, NULL)) {
5904 hdd_err("Invalid ATTR");
5905 return -EINVAL;
5906 }
5907
5908 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5909 hdd_err("attr tx power decrease db value failed");
5910 return -EINVAL;
5911 }
5912
5913 scale_value = nla_get_u8(tb
5914 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5915
Peng Xu62c8c432016-05-09 15:23:02 -07005916 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5917 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005918
Peng Xu62c8c432016-05-09 15:23:02 -07005919 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005920 hdd_err("Set tx power decrease db failed");
5921 return -EINVAL;
5922 }
5923
5924 return 0;
5925}
5926
5927/**
5928 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5929 * @wiphy: Pointer to wireless phy
5930 * @wdev: Pointer to wireless device
5931 * @data: Pointer to data
5932 * @data_len: Data length
5933 *
5934 * Return: 0 on success, negative errno on failure
5935 */
5936static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5937 struct wireless_dev *wdev,
5938 const void *data,
5939 int data_len)
5940{
Peng Xu62c8c432016-05-09 15:23:02 -07005941 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005942
5943 cds_ssr_protect(__func__);
5944 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5945 data, data_len);
5946 cds_ssr_unprotect(__func__);
5947
5948 return ret;
5949}
Peng Xu8fdaa492016-06-22 10:20:47 -07005950
5951/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305952 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5953 * @wiphy: Pointer to wireless phy
5954 * @wdev: Pointer to wireless device
5955 * @data: Pointer to data
5956 * @data_len: Data length
5957 *
5958 * Processes the conditional channel switch request and invokes the helper
5959 * APIs to process the channel switch request.
5960 *
5961 * Return: 0 on success, negative errno on failure
5962 */
5963static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5964 struct wireless_dev *wdev,
5965 const void *data,
5966 int data_len)
5967{
5968 int ret;
5969 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5970 struct net_device *dev = wdev->netdev;
5971 hdd_adapter_t *adapter;
5972 struct nlattr
5973 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5974 uint32_t freq_len, i;
5975 uint32_t *freq;
5976 uint8_t chans[QDF_MAX_NUM_CHAN];
5977
5978 ENTER_DEV(dev);
5979
5980 ret = wlan_hdd_validate_context(hdd_ctx);
5981 if (ret)
5982 return ret;
5983
5984 if (!hdd_ctx->config->enableDFSMasterCap) {
5985 hdd_err("DFS master capability is not present in the driver");
5986 return -EINVAL;
5987 }
5988
5989 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5990 hdd_err("Command not allowed in FTM mode");
5991 return -EPERM;
5992 }
5993
5994 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5995 if (adapter->device_mode != QDF_SAP_MODE) {
5996 hdd_err("Invalid device mode %d", adapter->device_mode);
5997 return -EINVAL;
5998 }
5999
6000 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6001 data, data_len, NULL)) {
6002 hdd_err("Invalid ATTR");
6003 return -EINVAL;
6004 }
6005
6006 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6007 hdd_err("Frequency list is missing");
6008 return -EINVAL;
6009 }
6010
6011 freq_len = nla_len(
6012 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6013 sizeof(uint32_t);
6014
6015 if (freq_len > QDF_MAX_NUM_CHAN) {
6016 hdd_err("insufficient space to hold channels");
6017 return -ENOMEM;
6018 }
6019
6020 hdd_debug("freq_len=%d", freq_len);
6021
6022 freq = nla_data(
6023 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6024
6025
6026 for (i = 0; i < freq_len; i++) {
6027 if (freq[i] == 0)
6028 chans[i] = 0;
6029 else
6030 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6031
6032 hdd_debug("freq[%d]=%d", i, freq[i]);
6033 }
6034
6035 /*
6036 * The input frequency list from user space is designed to be a
6037 * priority based frequency list. This is only to accommodate any
6038 * future request. But, current requirement is only to perform CAC
6039 * on a single channel. So, the first entry from the list is picked.
6040 *
6041 * If channel is zero, any channel in the available outdoor regulatory
6042 * domain will be selected.
6043 */
6044 ret = wlan_hdd_request_pre_cac(chans[0]);
6045 if (ret) {
6046 hdd_err("pre cac request failed with reason:%d", ret);
6047 return ret;
6048 }
6049
6050 return 0;
6051}
6052
6053/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006054 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6055 * @wiphy: Pointer to wireless phy
6056 * @wdev: Pointer to wireless device
6057 * @data: Pointer to data
6058 * @data_len: Data length
6059 *
6060 * This function is to process the p2p listen offload start vendor
6061 * command. It parses the input parameters and invoke WMA API to
6062 * send the command to firmware.
6063 *
6064 * Return: 0 on success, negative errno on failure
6065 */
6066static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6067 struct wireless_dev *wdev,
6068 const void *data,
6069 int data_len)
6070{
6071 int ret;
6072 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6073 struct net_device *dev = wdev->netdev;
6074 hdd_adapter_t *adapter;
6075 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6076 struct sir_p2p_lo_start params;
6077 QDF_STATUS status;
6078
6079 ENTER_DEV(dev);
6080
6081 ret = wlan_hdd_validate_context(hdd_ctx);
6082 if (ret)
6083 return ret;
6084
6085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6086 hdd_err("Command not allowed in FTM mode");
6087 return -EPERM;
6088 }
6089
6090 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6091 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6092 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6093 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6094 hdd_err("Invalid device mode %d", adapter->device_mode);
6095 return -EINVAL;
6096 }
6097
6098 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6099 data, data_len, NULL)) {
6100 hdd_err("Invalid ATTR");
6101 return -EINVAL;
6102 }
6103
6104 memset(&params, 0, sizeof(params));
6105
6106 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6107 params.ctl_flags = 1; /* set to default value */
6108 else
6109 params.ctl_flags = nla_get_u32(tb
6110 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6111
6112 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6113 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6114 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6115 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6116 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6117 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6118 hdd_err("Attribute parsing failed");
6119 return -EINVAL;
6120 }
6121
6122 params.vdev_id = adapter->sessionId;
6123 params.freq = nla_get_u32(tb
6124 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6125 if ((params.freq != 2412) && (params.freq != 2437) &&
6126 (params.freq != 2462)) {
6127 hdd_err("Invalid listening channel: %d", params.freq);
6128 return -EINVAL;
6129 }
6130
6131 params.period = nla_get_u32(tb
6132 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6133 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6134 hdd_err("Invalid period: %d", params.period);
6135 return -EINVAL;
6136 }
6137
6138 params.interval = nla_get_u32(tb
6139 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6140 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6141 hdd_err("Invalid interval: %d", params.interval);
6142 return -EINVAL;
6143 }
6144
6145 params.count = nla_get_u32(tb
6146 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6147 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6148 hdd_err("Invalid count: %d", params.count);
6149 return -EINVAL;
6150 }
6151
6152 params.device_types = nla_data(tb
6153 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6154 if (params.device_types == NULL) {
6155 hdd_err("Invalid device types");
6156 return -EINVAL;
6157 }
6158
6159 params.dev_types_len = nla_len(tb
6160 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6161 if (params.dev_types_len < 8) {
6162 hdd_err("Invalid device type length: %d", params.dev_types_len);
6163 return -EINVAL;
6164 }
6165
6166 params.probe_resp_tmplt = nla_data(tb
6167 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6168 if (params.probe_resp_tmplt == NULL) {
6169 hdd_err("Invalid probe response template");
6170 return -EINVAL;
6171 }
6172
6173 params.probe_resp_len = nla_len(tb
6174 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6175 if (params.probe_resp_len == 0) {
6176 hdd_err("Invalid probe resp template length: %d",
6177 params.probe_resp_len);
6178 return -EINVAL;
6179 }
6180
6181 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6182 params.freq, params.period, params.interval, params.count);
6183
6184 status = wma_p2p_lo_start(&params);
6185
6186 if (!QDF_IS_STATUS_SUCCESS(status)) {
6187 hdd_err("P2P LO start failed");
6188 return -EINVAL;
6189 }
6190
6191 return 0;
6192}
6193
6194
6195/**
6196 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6197 * @wiphy: Pointer to wireless phy
6198 * @wdev: Pointer to wireless device
6199 * @data: Pointer to data
6200 * @data_len: Data length
6201 *
6202 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6203 * to process p2p listen offload start vendor command.
6204 *
6205 * Return: 0 on success, negative errno on failure
6206 */
6207static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6208 struct wireless_dev *wdev,
6209 const void *data,
6210 int data_len)
6211{
6212 int ret = 0;
6213
6214 cds_ssr_protect(__func__);
6215 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6216 data, data_len);
6217 cds_ssr_unprotect(__func__);
6218
6219 return ret;
6220}
6221
6222/**
6223 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6224 * @wiphy: Pointer to wireless phy
6225 * @wdev: Pointer to wireless device
6226 * @data: Pointer to data
6227 * @data_len: Data length
6228 *
6229 * This function is to process the p2p listen offload stop vendor
6230 * command. It invokes WMA API to send command to firmware.
6231 *
6232 * Return: 0 on success, negative errno on failure
6233 */
6234static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6235 struct wireless_dev *wdev,
6236 const void *data,
6237 int data_len)
6238{
6239 QDF_STATUS status;
6240 hdd_adapter_t *adapter;
6241 struct net_device *dev = wdev->netdev;
6242
6243 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6244 hdd_err("Command not allowed in FTM mode");
6245 return -EPERM;
6246 }
6247
6248 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6249 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6250 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6251 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6252 hdd_err("Invalid device mode");
6253 return -EINVAL;
6254 }
6255
6256 status = wma_p2p_lo_stop(adapter->sessionId);
6257
6258 if (!QDF_IS_STATUS_SUCCESS(status)) {
6259 hdd_err("P2P LO stop failed");
6260 return -EINVAL;
6261 }
6262
6263 return 0;
6264}
6265
6266/**
6267 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6268 * @wiphy: Pointer to wireless phy
6269 * @wdev: Pointer to wireless device
6270 * @data: Pointer to data
6271 * @data_len: Data length
6272 *
6273 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6274 * to process p2p listen offload stop vendor command.
6275 *
6276 * Return: 0 on success, negative errno on failure
6277 */
6278static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6279 struct wireless_dev *wdev,
6280 const void *data,
6281 int data_len)
6282{
6283 int ret = 0;
6284
6285 cds_ssr_protect(__func__);
6286 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6287 data, data_len);
6288 cds_ssr_unprotect(__func__);
6289
6290 return ret;
6291}
6292
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306293/**
6294 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6295 * @wiphy: Pointer to wireless phy
6296 * @wdev: Pointer to wireless device
6297 * @data: Pointer to data
6298 * @data_len: Data length
6299 *
6300 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6301 * to process the conditional channel switch request.
6302 *
6303 * Return: 0 on success, negative errno on failure
6304 */
6305static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6306 struct wireless_dev *wdev,
6307 const void *data,
6308 int data_len)
6309{
6310 int ret;
6311
6312 cds_ssr_protect(__func__);
6313 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6314 data, data_len);
6315 cds_ssr_unprotect(__func__);
6316
6317 return ret;
6318}
6319
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306320/*
6321 * define short names for the global vendor params
6322 * used by __wlan_hdd_cfg80211_bpf_offload()
6323 */
6324#define BPF_INVALID \
6325 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6326#define BPF_SET_RESET \
6327 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6328#define BPF_VERSION \
6329 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6330#define BPF_FILTER_ID \
6331 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6332#define BPF_PACKET_SIZE \
6333 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6334#define BPF_CURRENT_OFFSET \
6335 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6336#define BPF_PROGRAM \
6337 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6338#define BPF_MAX \
6339 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006340
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306341static const struct nla_policy
6342wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6343 [BPF_SET_RESET] = {.type = NLA_U32},
6344 [BPF_VERSION] = {.type = NLA_U32},
6345 [BPF_FILTER_ID] = {.type = NLA_U32},
6346 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6347 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6348 [BPF_PROGRAM] = {.type = NLA_U8},
6349};
6350
6351/**
6352 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6353 * @hdd_context: hdd_context
6354 * @bpf_get_offload: struct for get offload
6355 *
6356 * This function receives the response/data from the lower layer and
6357 * checks to see if the thread is still waiting then post the results to
6358 * upper layer, if the request has timed out then ignore.
6359 *
6360 * Return: None
6361 */
6362void hdd_get_bpf_offload_cb(void *hdd_context,
6363 struct sir_bpf_get_offload *data)
6364{
6365 hdd_context_t *hdd_ctx = hdd_context;
6366 struct hdd_bpf_context *context;
6367
6368 ENTER();
6369
6370 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006371 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306372 data);
6373 return;
6374 }
6375
6376 spin_lock(&hdd_context_lock);
6377
6378 context = &bpf_context;
6379 /* The caller presumably timed out so there is nothing we can do */
6380 if (context->magic != BPF_CONTEXT_MAGIC) {
6381 spin_unlock(&hdd_context_lock);
6382 return;
6383 }
6384
6385 /* context is valid so caller is still waiting */
6386 /* paranoia: invalidate the magic */
6387 context->magic = 0;
6388
6389 context->capability_response = *data;
6390 complete(&context->completion);
6391
6392 spin_unlock(&hdd_context_lock);
6393
6394 return;
6395}
6396
6397/**
6398 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6399 * @hdd_context: hdd_context
6400 * @bpf_get_offload: struct for get offload
6401 *
6402 * Return: 0 on success, error number otherwise.
6403 */
6404static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6405 struct sir_bpf_get_offload *bpf_get_offload)
6406{
6407 struct sk_buff *skb;
6408 uint32_t nl_buf_len;
6409
6410 ENTER();
6411
6412 nl_buf_len = NLMSG_HDRLEN;
6413 nl_buf_len +=
6414 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6415 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6416
6417 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6418 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006419 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306420 return -ENOMEM;
6421 }
6422
Jeff Johnson77848112016-06-29 14:52:06 -07006423 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306424 bpf_get_offload->bpf_version,
6425 bpf_get_offload->max_bytes_for_bpf_inst);
6426
6427 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6428 bpf_get_offload->max_bytes_for_bpf_inst) ||
6429 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006430 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306431 goto nla_put_failure;
6432 }
6433
6434 cfg80211_vendor_cmd_reply(skb);
6435 EXIT();
6436 return 0;
6437
6438nla_put_failure:
6439 kfree_skb(skb);
6440 return -EINVAL;
6441}
6442
6443/**
6444 * hdd_get_bpf_offload - Get BPF offload Capabilities
6445 * @hdd_ctx: Hdd context
6446 *
6447 * Return: 0 on success, errno on failure
6448 */
6449static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6450{
6451 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006452 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306453 QDF_STATUS status;
6454 int ret;
6455
6456 ENTER();
6457
6458 spin_lock(&hdd_context_lock);
6459 context = &bpf_context;
6460 context->magic = BPF_CONTEXT_MAGIC;
6461 INIT_COMPLETION(context->completion);
6462 spin_unlock(&hdd_context_lock);
6463
6464 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6465 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006466 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306467 return -EINVAL;
6468 }
6469 /* request was sent -- wait for the response */
6470 rc = wait_for_completion_timeout(&context->completion,
6471 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6472 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006473 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306474 spin_lock(&hdd_context_lock);
6475 context->magic = 0;
6476 spin_unlock(&hdd_context_lock);
6477
6478 return -ETIMEDOUT;
6479 }
6480 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6481 &bpf_context.capability_response);
6482 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006483 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306484
6485 EXIT();
6486 return ret;
6487}
6488
6489/**
6490 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6491 * @hdd_ctx: Hdd context
6492 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306493 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306494 *
6495 * Return: 0 on success; errno on failure
6496 */
6497static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6498 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306499 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306500{
6501 struct sir_bpf_set_offload *bpf_set_offload;
6502 QDF_STATUS status;
6503 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306504 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306505
6506 ENTER();
6507
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306508 if (adapter->device_mode == QDF_STA_MODE ||
6509 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6510 if (!hdd_conn_is_connected(
6511 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6512 hdd_err("Not in Connected state!");
6513 return -ENOTSUPP;
6514 }
6515 }
6516
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306517 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6518 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006519 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306520 return -ENOMEM;
6521 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306522
6523 /* Parse and fetch bpf packet size */
6524 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006525 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306526 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306527 goto fail;
6528 }
6529 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6530
6531 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006532 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306533 goto post_sme;
6534 }
6535
6536 /* Parse and fetch bpf program */
6537 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006538 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306539 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306540 goto fail;
6541 }
6542
6543 prog_len = nla_len(tb[BPF_PROGRAM]);
6544 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306545
6546 if (bpf_set_offload->program == NULL) {
6547 hdd_err("qdf_mem_malloc failed for bpf offload program");
6548 ret = -ENOMEM;
6549 goto fail;
6550 }
6551
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306552 bpf_set_offload->current_length = prog_len;
6553 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306554 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306555
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306556 hdd_info("BPF set instructions");
6557 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6558 bpf_set_offload->program, prog_len);
6559
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306560 /* Parse and fetch filter Id */
6561 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006562 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306563 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306564 goto fail;
6565 }
6566 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6567
6568 /* Parse and fetch current offset */
6569 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006570 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306571 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306572 goto fail;
6573 }
6574 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6575
6576post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006577 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 +05306578 bpf_set_offload->session_id,
6579 bpf_set_offload->version,
6580 bpf_set_offload->filter_id,
6581 bpf_set_offload->total_length,
6582 bpf_set_offload->current_length,
6583 bpf_set_offload->current_offset);
6584
6585 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6586 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006587 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306588 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306589 goto fail;
6590 }
6591 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306592
6593fail:
6594 if (bpf_set_offload->current_length)
6595 qdf_mem_free(bpf_set_offload->program);
6596 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306597 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306598}
6599
6600/**
6601 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6602 * @wiphy: wiphy structure pointer
6603 * @wdev: Wireless device structure pointer
6604 * @data: Pointer to the data received
6605 * @data_len: Length of @data
6606 *
6607 * Return: 0 on success; errno on failure
6608 */
6609static int
6610__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6611 struct wireless_dev *wdev,
6612 const void *data, int data_len)
6613{
6614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6615 struct net_device *dev = wdev->netdev;
6616 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6617 struct nlattr *tb[BPF_MAX + 1];
6618 int ret_val, packet_filter_subcmd;
6619
6620 ENTER();
6621
6622 ret_val = wlan_hdd_validate_context(hdd_ctx);
6623 if (ret_val)
6624 return ret_val;
6625
6626 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006627 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306628 return -EINVAL;
6629 }
6630
6631 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006632 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306633 return -ENOTSUPP;
6634 }
6635
6636 if (nla_parse(tb, BPF_MAX, data, data_len,
6637 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006638 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306639 return -EINVAL;
6640 }
6641
6642 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006643 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306644 return -EINVAL;
6645 }
6646
6647 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6648
6649 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6650 return hdd_get_bpf_offload(hdd_ctx);
6651 else
6652 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306653 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306654}
6655
6656/**
6657 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6658 * @wiphy: wiphy structure pointer
6659 * @wdev: Wireless device structure pointer
6660 * @data: Pointer to the data received
6661 * @data_len: Length of @data
6662 *
6663 * Return: 0 on success; errno on failure
6664 */
6665
6666static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6667 struct wireless_dev *wdev,
6668 const void *data, int data_len)
6669{
6670 int ret;
6671
6672 cds_ssr_protect(__func__);
6673 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6674 cds_ssr_unprotect(__func__);
6675
6676 return ret;
6677}
6678
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306679/**
6680 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6681 * @pre_cac_adapter: AP adapter used for pre cac
6682 * @status: Status (true or false)
6683 * @handle: Global handle
6684 *
6685 * Sets the status of pre cac i.e., whether the pre cac is active or not
6686 *
6687 * Return: Zero on success, non-zero on failure
6688 */
6689static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6690 bool status, tHalHandle handle)
6691{
6692 QDF_STATUS ret;
6693
6694 ret = wlan_sap_set_pre_cac_status(
6695 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6696 if (QDF_IS_STATUS_ERROR(ret))
6697 return -EINVAL;
6698
6699 return 0;
6700}
6701
6702/**
6703 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6704 * @ap_adapter: AP adapter
6705 * @chan_before_pre_cac: Channel
6706 *
6707 * Saves the channel which the AP was beaconing on before moving to the pre
6708 * cac channel. If radar is detected on the pre cac channel, this saved
6709 * channel will be used for AP operations.
6710 *
6711 * Return: Zero on success, non-zero on failure
6712 */
6713static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6714 uint8_t chan_before_pre_cac)
6715{
6716 QDF_STATUS ret;
6717
6718 ret = wlan_sap_set_chan_before_pre_cac(
6719 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6720 if (QDF_IS_STATUS_ERROR(ret))
6721 return -EINVAL;
6722
6723 return 0;
6724}
6725
6726/**
6727 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6728 * @ap_adapter: AP adapter
6729 * @nol: Non-occupancy list
6730 * @nol_len: Length of NOL
6731 *
6732 * Get the NOL for SAP
6733 *
6734 * Return: Zero on success, non-zero on failure
6735 */
6736static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6737 uint32_t *nol_len)
6738{
6739 QDF_STATUS ret;
6740
6741 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6742 nol, nol_len);
6743 if (QDF_IS_STATUS_ERROR(ret))
6744 return -EINVAL;
6745
6746 return 0;
6747}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306748
6749/**
6750 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6751 * @hdd_ctx: HDD context
6752 * @ap_adapter: AP adapter
6753 * @channel: Channel requested by userspace
6754 * @pre_cac_chan: Pointer to the pre CAC channel
6755 *
6756 * Validates the channel provided by userspace. If user provided channel 0,
6757 * a valid outdoor channel must be selected from the regulatory channel.
6758 *
6759 * Return: Zero on success and non zero value on error
6760 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006761static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6762 hdd_adapter_t *ap_adapter,
6763 uint8_t channel,
6764 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306765{
6766 uint32_t i, j;
6767 QDF_STATUS status;
6768 int ret;
6769 uint8_t nol[QDF_MAX_NUM_CHAN];
6770 uint32_t nol_len = 0, weight_len = 0;
6771 bool found;
6772 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6773 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6774 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6775
6776 if (0 == channel) {
6777 /* Channel is not obtained from PCL because PCL may not have
6778 * the entire channel list. For example: if SAP is up on
6779 * channel 6 and PCL is queried for the next SAP interface,
6780 * if SCC is preferred, the PCL will contain only the channel
6781 * 6. But, we are in need of a DFS channel. So, going with the
6782 * first channel from the valid channel list.
6783 */
6784 status = cds_get_valid_chans(channel_list, &len);
6785 if (QDF_IS_STATUS_ERROR(status)) {
6786 hdd_err("Failed to get channel list");
6787 return -EINVAL;
6788 }
6789 cds_update_with_safe_channel_list(channel_list, &len,
6790 pcl_weights, weight_len);
6791 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6792 for (i = 0; i < len; i++) {
6793 found = false;
6794 for (j = 0; j < nol_len; j++) {
6795 if (channel_list[i] == nol[j]) {
6796 found = true;
6797 break;
6798 }
6799 }
6800 if (found)
6801 continue;
6802 if (CDS_IS_DFS_CH(channel_list[i])) {
6803 *pre_cac_chan = channel_list[i];
6804 break;
6805 }
6806 }
6807 if (*pre_cac_chan == 0) {
6808 hdd_err("unable to find outdoor channel");
6809 return -EINVAL;
6810 }
6811 } else {
6812 /* Only when driver selects a channel, check is done for
6813 * unnsafe and NOL channels. When user provides a fixed channel
6814 * the user is expected to take care of this.
6815 */
6816 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6817 !CDS_IS_DFS_CH(channel)) {
6818 hdd_err("Invalid channel for pre cac:%d", channel);
6819 return -EINVAL;
6820 } else {
6821 *pre_cac_chan = channel;
6822 }
6823 }
6824 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6825 return 0;
6826}
6827
6828/**
6829 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6830 * @channel: Channel option provided by userspace
6831 *
6832 * Sets the driver to the required hardware mode and start an adapater for
6833 * pre CAC which will mimic an AP.
6834 *
6835 * Return: Zero on success, non-zero value on error
6836 */
6837int wlan_hdd_request_pre_cac(uint8_t channel)
6838{
Krunal Sonib37bb352016-12-20 14:12:21 -08006839 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306840 hdd_context_t *hdd_ctx;
6841 int ret;
6842 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6843 hdd_ap_ctx_t *hdd_ap_ctx;
6844 QDF_STATUS status;
6845 struct wiphy *wiphy;
6846 struct net_device *dev;
6847 struct cfg80211_chan_def chandef;
6848 enum nl80211_channel_type channel_type;
6849 uint32_t freq;
6850 struct ieee80211_channel *chan;
6851 tHalHandle handle;
6852 bool val;
6853
6854 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6855 if (0 != wlan_hdd_validate_context(hdd_ctx))
6856 return -EINVAL;
6857
6858 if (cds_get_connection_count() > 1) {
6859 hdd_err("pre cac not allowed in concurrency");
6860 return -EINVAL;
6861 }
6862
6863 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6864 if (!ap_adapter) {
6865 hdd_err("unable to get SAP adapter");
6866 return -EINVAL;
6867 }
6868
6869 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6870 if (!handle) {
6871 hdd_err("Invalid handle");
6872 return -EINVAL;
6873 }
6874
6875 val = wlan_sap_is_pre_cac_active(handle);
6876 if (val) {
6877 hdd_err("pre cac is already in progress");
6878 return -EINVAL;
6879 }
6880
6881 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6882 if (!hdd_ap_ctx) {
6883 hdd_err("SAP context is NULL");
6884 return -EINVAL;
6885 }
6886
6887 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6888 hdd_err("SAP is already on DFS channel:%d",
6889 hdd_ap_ctx->operatingChannel);
6890 return -EINVAL;
6891 }
6892
6893 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6894 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6895 hdd_ap_ctx->operatingChannel);
6896 return -EINVAL;
6897 }
6898
Krunal Sonib37bb352016-12-20 14:12:21 -08006899 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6900 if (!mac_addr) {
6901 hdd_err("can't add virtual intf: Not getting valid mac addr");
6902 return -EINVAL;
6903 }
6904
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306905 hdd_info("channel:%d", channel);
6906
6907 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6908 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006909 if (ret != 0) {
6910 hdd_err("can't validate pre-cac channel");
6911 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306912 }
6913
6914 hdd_debug("starting pre cac SAP adapter");
6915
6916 /* Starting a SAP adapter:
6917 * Instead of opening an adapter, we could just do a SME open session
6918 * for AP type. But, start BSS would still need an adapter.
6919 * So, this option is not taken.
6920 *
6921 * hdd open adapter is going to register this precac interface with
6922 * user space. This interface though exposed to user space will be in
6923 * DOWN state. Consideration was done to avoid this registration to the
6924 * user space. But, as part of SAP operations multiple events are sent
6925 * to user space. Some of these events received from unregistered
6926 * interface was causing crashes. So, retaining the registration.
6927 *
6928 * So, this interface would remain registered and will remain in DOWN
6929 * state for the CAC duration. We will add notes in the feature
6930 * announcement to not use this temporary interface for any activity
6931 * from user space.
6932 */
6933 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006934 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306935 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306936 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006937 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306938 }
6939
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306940 /*
6941 * This interface is internally created by the driver. So, no interface
6942 * up comes for this interface from user space and hence starting
6943 * the adapter internally.
6944 */
6945 if (hdd_start_adapter(pre_cac_adapter)) {
6946 hdd_err("error starting the pre cac adapter");
6947 goto close_pre_cac_adapter;
6948 }
6949
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306950 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6951
6952 wiphy = hdd_ctx->wiphy;
6953 dev = pre_cac_adapter->dev;
6954
6955 /* Since this is only a dummy interface lets us use the IEs from the
6956 * other active SAP interface. In regular scenarios, these IEs would
6957 * come from the user space entity
6958 */
6959 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6960 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6961 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6962 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306963 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306964 }
6965 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6966 ap_adapter->sessionCtx.ap.beacon,
6967 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6968 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6969 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6970 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6971 ap_adapter->sessionCtx.ap.sapConfig.authType;
6972
6973 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6974 * to operate on the same bandwidth as that of the 2.4GHz operations.
6975 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6976 */
6977 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6978 case CH_WIDTH_20MHZ:
6979 channel_type = NL80211_CHAN_HT20;
6980 break;
6981 case CH_WIDTH_40MHZ:
6982 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6983 ap_adapter->sessionCtx.ap.sapConfig.channel)
6984 channel_type = NL80211_CHAN_HT40PLUS;
6985 else
6986 channel_type = NL80211_CHAN_HT40MINUS;
6987 break;
6988 default:
6989 channel_type = NL80211_CHAN_NO_HT;
6990 break;
6991 }
6992
6993 freq = cds_chan_to_freq(pre_cac_chan);
6994 chan = __ieee80211_get_channel(wiphy, freq);
6995 if (!chan) {
6996 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306997 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306998 }
6999
7000 cfg80211_chandef_create(&chandef, chan, channel_type);
7001
7002 hdd_debug("orig width:%d channel_type:%d freq:%d",
7003 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7004 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007005 /*
7006 * Doing update after opening and starting pre-cac adapter will make
7007 * sure that driver won't do hardware mode change if there are any
7008 * initial hick-ups or issues in pre-cac adapter's configuration.
7009 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7010 * connection update should result in DBS mode
7011 */
7012 status = cds_update_and_wait_for_connection_update(
7013 ap_adapter->sessionId,
7014 pre_cac_chan,
7015 SIR_UPDATE_REASON_PRE_CAC);
7016 if (QDF_IS_STATUS_ERROR(status)) {
7017 hdd_err("error in moving to DBS mode");
7018 goto stop_close_pre_cac_adapter;
7019 }
7020
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307021
7022 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7023 if (0 != ret) {
7024 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307025 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307026 }
7027
7028 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7029 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007030 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307031 if (QDF_IS_STATUS_ERROR(status)) {
7032 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307033 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307034 }
7035
7036 /*
7037 * The pre cac status is set here. But, it would not be reset explicitly
7038 * anywhere, since after the pre cac success/failure, the pre cac
7039 * adapter itself would be removed.
7040 */
7041 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7042 if (0 != ret) {
7043 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307044 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307045 }
7046
7047 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7048 hdd_ap_ctx->operatingChannel);
7049 if (0 != ret) {
7050 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307051 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307052 }
7053
7054 ap_adapter->pre_cac_chan = pre_cac_chan;
7055
7056 return 0;
7057
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307058stop_close_pre_cac_adapter:
7059 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307060 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7061 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307062close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307063 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007064release_intf_addr_and_return_failure:
7065 /*
7066 * Release the interface address as the adapter
7067 * failed to start, if you don't release then next
7068 * adapter which is trying to come wouldn't get valid
7069 * mac address. Remember we have limited pool of mac addresses
7070 */
7071 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307072 return -EINVAL;
7073}
7074
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307075/**
7076 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7077 *
7078 * Return: None
7079 */
7080void hdd_init_bpf_completion(void)
7081{
7082 init_completion(&bpf_context.completion);
7083}
7084
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307085static const struct nla_policy
7086wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7087 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7088};
7089
Agrawal Ashish65634612016-08-18 13:24:32 +05307090static const struct nla_policy
7091wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7092 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7093 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7094};
7095
7096/**
7097 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7098 * @wiphy: Pointer to wireless phy
7099 * @wdev: Pointer to wireless device
7100 * @data: Pointer to data
7101 * @data_len: Length of @data
7102 *
7103 * This function parses the incoming NL vendor command data attributes and
7104 * updates the SAP context about channel_hint and DFS mode.
7105 * If channel_hint is set, SAP will choose that channel
7106 * as operating channel.
7107 *
7108 * If DFS mode is enabled, driver will include DFS channels
7109 * in ACS else driver will skip DFS channels.
7110 *
7111 * Return: 0 on success, negative errno on failure
7112 */
7113static int
7114__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7115 struct wireless_dev *wdev,
7116 const void *data, int data_len)
7117{
7118 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7119 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7120 int ret;
7121 struct acs_dfs_policy *acs_policy;
7122 int mode = DFS_MODE_NONE;
7123 int channel_hint = 0;
7124
7125 ENTER_DEV(wdev->netdev);
7126
7127 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7128 hdd_err("Command not allowed in FTM mode");
7129 return -EINVAL;
7130 }
7131
7132 ret = wlan_hdd_validate_context(hdd_ctx);
7133 if (0 != ret)
7134 return ret;
7135
7136 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7137 data, data_len,
7138 wlan_hdd_set_acs_dfs_config_policy)) {
7139 hdd_err("invalid attr");
7140 return -EINVAL;
7141 }
7142
7143 acs_policy = &hdd_ctx->acs_policy;
7144 /*
7145 * SCM sends this attribute to restrict SAP from choosing
7146 * DFS channels from ACS.
7147 */
7148 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7149 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7150
7151 if (!IS_DFS_MODE_VALID(mode)) {
7152 hdd_err("attr acs dfs mode is not valid");
7153 return -EINVAL;
7154 }
7155 acs_policy->acs_dfs_mode = mode;
7156
7157 /*
7158 * SCM sends this attribute to provide an active channel,
7159 * to skip redundant ACS between drivers, and save driver start up time
7160 */
7161 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7162 channel_hint = nla_get_u8(
7163 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7164
7165 if (!IS_CHANNEL_VALID(channel_hint)) {
7166 hdd_err("acs channel is not valid");
7167 return -EINVAL;
7168 }
7169 acs_policy->acs_channel = channel_hint;
7170
7171 return 0;
7172}
7173
7174/**
7175 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7176 * @wiphy: wiphy structure pointer
7177 * @wdev: Wireless device structure pointer
7178 * @data: Pointer to the data received
7179 * @data_len: Length of @data
7180 *
7181 * This function parses the incoming NL vendor command data attributes and
7182 * updates the SAP context about channel_hint and DFS mode.
7183 *
7184 * Return: 0 on success; errno on failure
7185 */
7186static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7187 struct wireless_dev *wdev,
7188 const void *data, int data_len)
7189{
7190 int ret;
7191
7192 cds_ssr_protect(__func__);
7193 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7194 cds_ssr_unprotect(__func__);
7195
7196 return ret;
7197}
7198
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307199/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307200 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7201 * @mode : cfg80211 dfs mode
7202 *
7203 * Return: return csr sta roam dfs mode else return NONE
7204 */
7205static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7206 enum dfs_mode mode)
7207{
7208 switch (mode) {
7209 case DFS_MODE_ENABLE:
7210 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7211 break;
7212 case DFS_MODE_DISABLE:
7213 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7214 break;
7215 case DFS_MODE_DEPRIORITIZE:
7216 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7217 break;
7218 default:
7219 hdd_err("STA Roam policy dfs mode is NONE");
7220 return CSR_STA_ROAM_POLICY_NONE;
7221 }
7222}
7223
7224static const struct nla_policy
7225wlan_hdd_set_sta_roam_config_policy[
7226QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7227 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7228 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7229};
7230
7231/**
7232 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7233 * for station connection or roaming.
7234 * @wiphy: Pointer to wireless phy
7235 * @wdev: Pointer to wireless device
7236 * @data: Pointer to data
7237 * @data_len: Length of @data
7238 *
7239 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7240 * channels needs to be skipped in scanning or not.
7241 * If dfs_mode is disabled, driver will not scan DFS channels.
7242 * If skip_unsafe_channels is set, driver will skip unsafe channels
7243 * in Scanning.
7244 *
7245 * Return: 0 on success, negative errno on failure
7246 */
7247static int
7248__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7249 struct wireless_dev *wdev,
7250 const void *data, int data_len)
7251{
7252 struct net_device *dev = wdev->netdev;
7253 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7254 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7255 struct nlattr *tb[
7256 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7257 int ret;
7258 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7259 enum dfs_mode mode = DFS_MODE_NONE;
7260 bool skip_unsafe_channels = false;
7261 QDF_STATUS status;
7262
7263 ENTER_DEV(dev);
7264
7265 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7266 hdd_err("Command not allowed in FTM mode");
7267 return -EINVAL;
7268 }
7269
7270 ret = wlan_hdd_validate_context(hdd_ctx);
7271 if (0 != ret)
7272 return ret;
7273 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7274 data, data_len,
7275 wlan_hdd_set_sta_roam_config_policy)) {
7276 hdd_err("invalid attr");
7277 return -EINVAL;
7278 }
7279 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7280 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7281 if (!IS_DFS_MODE_VALID(mode)) {
7282 hdd_err("attr sta roam dfs mode policy is not valid");
7283 return -EINVAL;
7284 }
7285
7286 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7287
7288 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7289 skip_unsafe_channels = nla_get_u8(
7290 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7291
7292 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7293 skip_unsafe_channels, adapter->sessionId);
7294
7295 if (!QDF_IS_STATUS_SUCCESS(status)) {
7296 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7297 return -EINVAL;
7298 }
7299 return 0;
7300}
7301
7302/**
7303 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7304 * connection and roaming for station.
7305 * @wiphy: wiphy structure pointer
7306 * @wdev: Wireless device structure pointer
7307 * @data: Pointer to the data received
7308 * @data_len: Length of @data
7309 *
7310 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7311 * channels needs to be skipped in scanning or not.
7312 * If dfs_mode is disabled, driver will not scan DFS channels.
7313 * If skip_unsafe_channels is set, driver will skip unsafe channels
7314 * in Scanning.
7315 * Return: 0 on success; errno on failure
7316 */
7317static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7318 struct wireless_dev *wdev,
7319 const void *data, int data_len)
7320{
7321 int ret;
7322
7323 cds_ssr_protect(__func__);
7324 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7325 cds_ssr_unprotect(__func__);
7326
7327 return ret;
7328}
7329
Agrawal Ashish467dde42016-09-08 18:44:22 +05307330#ifdef FEATURE_WLAN_CH_AVOID
7331/**
7332 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7333 * is on unsafe channel.
7334 * @wiphy: wiphy structure pointer
7335 * @wdev: Wireless device structure pointer
7336 * @data: Pointer to the data received
7337 * @data_len: Length of @data
7338 *
7339 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7340 * on any of unsafe channels.
7341 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7342 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7343 *
7344 * Return: 0 on success; errno on failure
7345 */
7346static int
7347__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7348 struct wireless_dev *wdev,
7349 const void *data, int data_len)
7350{
7351 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7352 int ret;
7353 uint16_t unsafe_channel_count;
7354 int unsafe_channel_index;
7355 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7356
7357 ENTER_DEV(wdev->netdev);
7358
7359 if (!qdf_ctx) {
7360 cds_err("qdf_ctx is NULL");
7361 return -EINVAL;
7362 }
7363
7364 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7365 hdd_err("Command not allowed in FTM mode");
7366 return -EINVAL;
7367 }
7368
7369 ret = wlan_hdd_validate_context(hdd_ctx);
7370 if (0 != ret)
7371 return ret;
7372 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7373 &(hdd_ctx->unsafe_channel_count),
7374 sizeof(hdd_ctx->unsafe_channel_list));
7375
7376 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7377 (uint16_t)NUM_CHANNELS);
7378 for (unsafe_channel_index = 0;
7379 unsafe_channel_index < unsafe_channel_count;
7380 unsafe_channel_index++) {
7381 hdd_info("Channel %d is not safe",
7382 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7383 }
7384 hdd_unsafe_channel_restart_sap(hdd_ctx);
7385 return 0;
7386}
7387
7388/**
7389 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7390 * is on unsafe channel.
7391 * @wiphy: wiphy structure pointer
7392 * @wdev: Wireless device structure pointer
7393 * @data: Pointer to the data received
7394 * @data_len: Length of @data
7395 *
7396 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7397 * on any of unsafe channels.
7398 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7399 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7400 *
7401 * Return: 0 on success; errno on failure
7402 */
7403static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7404 struct wireless_dev *wdev,
7405 const void *data, int data_len)
7406{
7407 int ret;
7408
7409 cds_ssr_protect(__func__);
7410 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7411 cds_ssr_unprotect(__func__);
7412
7413 return ret;
7414}
7415
7416#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307417/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307418 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7419 * SAP is on unsafe channel.
7420 * @wiphy: wiphy structure pointer
7421 * @wdev: Wireless device structure pointer
7422 * @data: Pointer to the data received
7423 * @data_len: Length of @data
7424 *
7425 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7426 * driver.
7427 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7428 * will initiate restart of sap.
7429 *
7430 * Return: 0 on success; errno on failure
7431 */
7432static int
7433__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7434 struct wireless_dev *wdev,
7435 const void *data, int data_len)
7436{
7437 struct net_device *ndev = wdev->netdev;
7438 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7439 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7440 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7441 uint8_t config_channel = 0;
7442 hdd_ap_ctx_t *ap_ctx;
7443 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307444 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307445
7446 ENTER();
7447
7448 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007449 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307450 return -EINVAL;
7451 }
7452
7453 ret = wlan_hdd_validate_context(hdd_ctx);
7454 if (0 != ret)
7455 return -EINVAL;
7456
7457 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7458 data, data_len,
7459 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007460 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307461 return -EINVAL;
7462 }
7463
7464 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7465 if (!test_bit(SOFTAP_BSS_STARTED,
7466 &hostapd_adapter->event_flags)) {
7467 hdd_err("SAP is not started yet. Restart sap will be invalid");
7468 return -EINVAL;
7469 }
7470
7471 config_channel =
7472 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7473
7474 if (!((IS_24G_CH(config_channel)) ||
7475 (IS_5G_CH(config_channel)))) {
7476 hdd_err("Channel %d is not valid to restart SAP",
7477 config_channel);
7478 return -ENOTSUPP;
7479 }
7480
7481 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7482 ap_ctx->sapConfig.channel = config_channel;
7483 ap_ctx->sapConfig.ch_params.ch_width =
7484 ap_ctx->sapConfig.ch_width_orig;
7485
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007486 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307487 ap_ctx->sapConfig.sec_ch,
7488 &ap_ctx->sapConfig.ch_params);
7489
7490 cds_restart_sap(hostapd_adapter);
7491 }
7492
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307493 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7494 uint32_t freq_len, i;
7495 uint32_t *freq;
7496 uint8_t chans[QDF_MAX_NUM_CHAN];
7497
7498 hdd_debug("setting mandatory freq/chan list");
7499
7500 freq_len = nla_len(
7501 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7502 sizeof(uint32_t);
7503
7504 if (freq_len > QDF_MAX_NUM_CHAN) {
7505 hdd_err("insufficient space to hold channels");
7506 return -ENOMEM;
7507 }
7508
7509 freq = nla_data(
7510 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7511
7512 hdd_debug("freq_len=%d", freq_len);
7513
7514 for (i = 0; i < freq_len; i++) {
7515 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7516 hdd_debug("freq[%d]=%d", i, freq[i]);
7517 }
7518
7519 status = cds_set_sap_mandatory_channels(chans, freq_len);
7520 if (QDF_IS_STATUS_ERROR(status))
7521 return -EINVAL;
7522 }
7523
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307524 return 0;
7525}
7526
7527/**
7528 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7529 * @wiphy: wiphy structure pointer
7530 * @wdev: Wireless device structure pointer
7531 * @data: Pointer to the data received
7532 * @data_len: Length of @data
7533 *
7534 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7535 * driver.
7536 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7537 * will initiate restart of sap.
7538 *
7539 * Return: 0 on success; errno on failure
7540 */
7541static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7542 struct wireless_dev *wdev,
7543 const void *data, int data_len)
7544{
7545 int ret;
7546
7547 cds_ssr_protect(__func__);
7548 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7549 wdev, data, data_len);
7550 cds_ssr_unprotect(__func__);
7551
7552 return ret;
7553}
7554
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307555#undef BPF_INVALID
7556#undef BPF_SET_RESET
7557#undef BPF_VERSION
7558#undef BPF_ID
7559#undef BPF_PACKET_SIZE
7560#undef BPF_CURRENT_OFFSET
7561#undef BPF_PROGRAM
7562#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307563
7564/**
7565 * define short names for the global vendor params
7566 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7567 */
7568#define PARAM_TOTAL_CMD_EVENT_WAKE \
7569 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7570#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7571 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7572#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7573 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7574#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7575 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7576#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7577 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7578#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7579 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7580#define PARAM_TOTAL_RX_DATA_WAKE \
7581 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7582#define PARAM_RX_UNICAST_CNT \
7583 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7584#define PARAM_RX_MULTICAST_CNT \
7585 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7586#define PARAM_RX_BROADCAST_CNT \
7587 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7588#define PARAM_ICMP_PKT \
7589 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7590#define PARAM_ICMP6_PKT \
7591 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7592#define PARAM_ICMP6_RA \
7593 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7594#define PARAM_ICMP6_NA \
7595 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7596#define PARAM_ICMP6_NS \
7597 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7598#define PARAM_ICMP4_RX_MULTICAST_CNT \
7599 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7600#define PARAM_ICMP6_RX_MULTICAST_CNT \
7601 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7602#define PARAM_OTHER_RX_MULTICAST_CNT \
7603 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7604
7605
7606/**
7607 * hdd_send_wakelock_stats() - API to send wakelock stats
7608 * @ctx: context to be passed to callback
7609 * @data: data passed to callback
7610 *
7611 * This function is used to send wake lock stats to HAL layer
7612 *
7613 * Return: 0 on success, error number otherwise.
7614 */
7615static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7616 const struct sir_wake_lock_stats *data)
7617{
7618 struct sk_buff *skb;
7619 uint32_t nl_buf_len;
7620 uint32_t total_rx_data_wake, rx_multicast_cnt;
7621 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307622 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307623
7624 ENTER();
7625
7626 nl_buf_len = NLMSG_HDRLEN;
7627 nl_buf_len +=
7628 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7629 (NLMSG_HDRLEN + sizeof(uint32_t));
7630
7631 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7632
7633 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007634 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307635 return -ENOMEM;
7636 }
7637
Jeff Johnson64943bd2016-08-23 13:14:06 -07007638 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307639 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007640 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307641 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007642 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307643 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007644 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307645 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007646 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307647 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007648 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307649 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007650 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307651 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007652 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7653 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307654 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307655
7656 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307657 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307658
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307659 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307660 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307661
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307662 rx_multicast_cnt =
7663 data->wow_ipv4_mcast_wake_up_count +
7664 ipv6_rx_multicast_addr_cnt;
7665
7666 total_rx_data_wake =
7667 data->wow_ucast_wake_up_count +
7668 data->wow_bcast_wake_up_count +
7669 rx_multicast_cnt;
7670
7671 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7672 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7673 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7674 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7675 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7676 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7677 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7678 total_rx_data_wake) ||
7679 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7680 data->wow_ucast_wake_up_count) ||
7681 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7682 rx_multicast_cnt) ||
7683 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7684 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307685 nla_put_u32(skb, PARAM_ICMP_PKT,
7686 data->wow_icmpv4_count) ||
7687 nla_put_u32(skb, PARAM_ICMP6_PKT,
7688 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307689 nla_put_u32(skb, PARAM_ICMP6_RA,
7690 data->wow_ipv6_mcast_ra_stats) ||
7691 nla_put_u32(skb, PARAM_ICMP6_NA,
7692 data->wow_ipv6_mcast_na_stats) ||
7693 nla_put_u32(skb, PARAM_ICMP6_NS,
7694 data->wow_ipv6_mcast_ns_stats) ||
7695 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7696 data->wow_ipv4_mcast_wake_up_count) ||
7697 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7698 ipv6_rx_multicast_addr_cnt) ||
7699 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007700 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307701 goto nla_put_failure;
7702 }
7703
7704 cfg80211_vendor_cmd_reply(skb);
7705
7706 EXIT();
7707 return 0;
7708
7709nla_put_failure:
7710 kfree_skb(skb);
7711 return -EINVAL;
7712}
7713
7714/**
7715 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7716 * @wiphy: wiphy pointer
7717 * @wdev: pointer to struct wireless_dev
7718 * @data: pointer to incoming NL vendor data
7719 * @data_len: length of @data
7720 *
7721 * This function parses the incoming NL vendor command data attributes and
7722 * invokes the SME Api and blocks on a completion variable.
7723 * WMA copies required data and invokes callback
7724 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7725 *
7726 * Return: 0 on success; error number otherwise.
7727 */
7728static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7729 struct wireless_dev *wdev,
7730 const void *data,
7731 int data_len)
7732{
7733 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7734 int status, ret;
7735 struct sir_wake_lock_stats wake_lock_stats;
7736 QDF_STATUS qdf_status;
7737
7738 ENTER();
7739
7740 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007741 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307742 return -EINVAL;
7743 }
7744
7745 status = wlan_hdd_validate_context(hdd_ctx);
7746 if (0 != status)
7747 return -EINVAL;
7748
7749 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7750 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007751 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307752 return -EINVAL;
7753 }
7754
7755 ret = hdd_send_wakelock_stats(hdd_ctx,
7756 &wake_lock_stats);
7757 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007758 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307759
7760 EXIT();
7761 return ret;
7762}
7763
7764/**
7765 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7766 * @wiphy: wiphy pointer
7767 * @wdev: pointer to struct wireless_dev
7768 * @data: pointer to incoming NL vendor data
7769 * @data_len: length of @data
7770 *
7771 * This function parses the incoming NL vendor command data attributes and
7772 * invokes the SME Api and blocks on a completion variable.
7773 * WMA copies required data and invokes callback
7774 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7775 *
7776 * Return: 0 on success; error number otherwise.
7777 */
7778static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7779 struct wireless_dev *wdev,
7780 const void *data, int data_len)
7781{
7782 int ret;
7783
7784 cds_ssr_protect(__func__);
7785 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7786 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007787 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307788
7789 return ret;
7790}
7791
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307792/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307793 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7794 * @wiphy: wiphy structure pointer
7795 * @wdev: Wireless device structure pointer
7796 * @data: Pointer to the data received
7797 * @data_len: Length of @data
7798 *
7799 * This function reads wmi max bus size and fill in the skb with
7800 * NL attributes and send up the NL event.
7801 * Return: 0 on success; errno on failure
7802 */
7803static int
7804__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7805 struct wireless_dev *wdev,
7806 const void *data, int data_len)
7807{
7808 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7809 int ret_val;
7810 struct sk_buff *skb;
7811 uint32_t nl_buf_len;
7812
7813 ENTER();
7814
7815 ret_val = wlan_hdd_validate_context(hdd_ctx);
7816 if (ret_val)
7817 return ret_val;
7818
7819 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7820 hdd_err("Command not allowed in FTM mode");
7821 return -EINVAL;
7822 }
7823
7824 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7825
7826 nl_buf_len = NLMSG_HDRLEN;
7827 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7828
7829 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7830 if (!skb) {
7831 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7832 return -ENOMEM;
7833 }
7834
7835 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7836 hdd_ctx->wmi_max_len)) {
7837 hdd_err("nla put failure");
7838 goto nla_put_failure;
7839 }
7840
7841 cfg80211_vendor_cmd_reply(skb);
7842
7843 EXIT();
7844
7845 return 0;
7846
7847nla_put_failure:
7848 kfree_skb(skb);
7849 return -EINVAL;
7850}
7851
7852/**
7853 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7854 * @wiphy: wiphy structure pointer
7855 * @wdev: Wireless device structure pointer
7856 * @data: Pointer to the data received
7857 * @data_len: Length of @data
7858 *
7859 * Return: 0 on success; errno on failure
7860 */
7861static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7862 struct wireless_dev *wdev,
7863 const void *data, int data_len)
7864{
7865 int ret;
7866
7867 cds_ssr_protect(__func__);
7868 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7869 cds_ssr_unprotect(__func__);
7870
7871 return ret;
7872}
7873
7874/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307875 *__wlan_hdd_cfg80211_setband() - set band
7876 * @wiphy: Pointer to wireless phy
7877 * @wdev: Pointer to wireless device
7878 * @data: Pointer to data
7879 * @data_len: Length of @data
7880 *
7881 * Return: 0 on success, negative errno on failure
7882 */
7883static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7884 struct wireless_dev *wdev,
7885 const void *data, int data_len)
7886{
7887 struct net_device *dev = wdev->netdev;
7888 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7889 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7890 int ret;
7891 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7892 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7893
7894 ENTER();
7895
7896 ret = wlan_hdd_validate_context(hdd_ctx);
7897 if (ret)
7898 return ret;
7899
7900 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7901 hdd_err(FL("Invalid ATTR"));
7902 return -EINVAL;
7903 }
7904
7905 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7906 hdd_err(FL("attr SETBAND_VALUE failed"));
7907 return -EINVAL;
7908 }
7909
7910 ret = hdd_set_band(dev,
7911 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7912
7913 EXIT();
7914 return ret;
7915}
7916
7917/**
7918 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7919 * @wiphy: wiphy structure pointer
7920 * @wdev: Wireless device structure pointer
7921 * @data: Pointer to the data received
7922 * @data_len: Length of @data
7923 *
7924 * Return: 0 on success; errno on failure
7925 */
7926static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7927 struct wireless_dev *wdev,
7928 const void *data, int data_len)
7929{
7930 int ret;
7931
7932 cds_ssr_protect(__func__);
7933 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7934 cds_ssr_unprotect(__func__);
7935
7936 return ret;
7937}
7938
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307939static const struct
7940nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7941 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7942 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7943 .len = QDF_MAC_ADDR_SIZE},
7944};
7945
7946/**
7947 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7948 * @wiphy: Pointer to wireless phy
7949 * @wdev: Pointer to wireless device
7950 * @data: Pointer to data
7951 * @data_len: Length of @data
7952 *
7953 * This function is used to enable/disable roaming using vendor commands
7954 *
7955 * Return: 0 on success, negative errno on failure
7956 */
7957static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7958 struct wireless_dev *wdev,
7959 const void *data, int data_len)
7960{
7961 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7962 struct net_device *dev = wdev->netdev;
7963 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7964 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7965 uint32_t is_fast_roam_enabled;
7966 int ret;
7967
7968 ENTER_DEV(dev);
7969
7970 ret = wlan_hdd_validate_context(hdd_ctx);
7971 if (0 != ret)
7972 return ret;
7973
7974 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7975 hdd_err("Command not allowed in FTM mode");
7976 return -EINVAL;
7977 }
7978
7979 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7980 qca_wlan_vendor_attr);
7981 if (ret) {
7982 hdd_err("Invalid ATTR");
7983 return -EINVAL;
7984 }
7985
7986 /* Parse and fetch Enable flag */
7987 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7988 hdd_err("attr enable failed");
7989 return -EINVAL;
7990 }
7991
7992 is_fast_roam_enabled = nla_get_u32(
7993 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7994 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7995
7996 /* Update roaming */
7997 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7998 is_fast_roam_enabled);
7999 if (ret)
8000 hdd_err("sme_config_fast_roaming failed");
8001 EXIT();
8002 return ret;
8003}
8004
8005/**
8006 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8007 * @wiphy: Pointer to wireless phy
8008 * @wdev: Pointer to wireless device
8009 * @data: Pointer to data
8010 * @data_len: Length of @data
8011 *
8012 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8013 *
8014 * Return: 0 on success, negative errno on failure
8015 */
8016static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8017 struct wireless_dev *wdev,
8018 const void *data, int data_len)
8019{
8020 int ret;
8021
8022 cds_ssr_protect(__func__);
8023 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8024 cds_ssr_unprotect(__func__);
8025
8026 return ret;
8027}
8028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008029const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8030 {
8031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8032 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8033 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308034 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008035 .doit = is_driver_dfs_capable
8036 },
8037
8038#ifdef WLAN_FEATURE_NAN
8039 {
8040 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8041 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8042 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8043 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8044 .doit = wlan_hdd_cfg80211_nan_request
8045 },
8046#endif
8047
8048#ifdef WLAN_FEATURE_STATS_EXT
8049 {
8050 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8051 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8052 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8053 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8054 .doit = wlan_hdd_cfg80211_stats_ext_request
8055 },
8056#endif
8057#ifdef FEATURE_WLAN_EXTSCAN
8058 {
8059 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8060 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8061 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8062 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8063 .doit = wlan_hdd_cfg80211_extscan_start
8064 },
8065 {
8066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8069 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8070 .doit = wlan_hdd_cfg80211_extscan_stop
8071 },
8072 {
8073 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8074 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8075 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8076 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8077 },
8078 {
8079 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8080 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8081 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8082 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8083 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8084 },
8085 {
8086 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8087 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8088 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8089 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8090 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8091 },
8092 {
8093 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8094 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8095 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8096 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8097 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8098 },
8099 {
8100 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8101 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8102 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8103 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8104 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8105 },
8106 {
8107 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8108 .info.subcmd =
8109 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8110 .flags =
8111 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8112 WIPHY_VENDOR_CMD_NEED_RUNNING,
8113 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8114 },
8115 {
8116 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8117 .info.subcmd =
8118 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8119 .flags =
8120 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8121 WIPHY_VENDOR_CMD_NEED_RUNNING,
8122 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8123 },
8124 {
8125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8128 WIPHY_VENDOR_CMD_NEED_NETDEV |
8129 WIPHY_VENDOR_CMD_NEED_RUNNING,
8130 .doit = wlan_hdd_cfg80211_set_epno_list
8131 },
8132#endif /* FEATURE_WLAN_EXTSCAN */
8133
8134#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8135 {
8136 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8137 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8138 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8139 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8140 .doit = wlan_hdd_cfg80211_ll_stats_clear
8141 },
8142
8143 {
8144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8147 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8148 .doit = wlan_hdd_cfg80211_ll_stats_set
8149 },
8150
8151 {
8152 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8153 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8154 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8155 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8156 .doit = wlan_hdd_cfg80211_ll_stats_get
8157 },
8158#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8159#ifdef FEATURE_WLAN_TDLS
8160 {
8161 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8162 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8163 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8164 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8165 .doit = wlan_hdd_cfg80211_exttdls_enable
8166 },
8167 {
8168 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8169 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8170 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8171 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8172 .doit = wlan_hdd_cfg80211_exttdls_disable
8173 },
8174 {
8175 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8176 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8177 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8178 .doit = wlan_hdd_cfg80211_exttdls_get_status
8179 },
8180#endif
8181 {
8182 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8183 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8184 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8185 .doit = wlan_hdd_cfg80211_get_supported_features
8186 },
8187 {
8188 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8189 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8190 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8191 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8192 },
8193 {
8194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8195 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8196 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308197 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008198 },
8199 {
8200 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8201 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8203 WIPHY_VENDOR_CMD_NEED_NETDEV,
8204 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8205 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008206 {
8207 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8208 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8209 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8210 WIPHY_VENDOR_CMD_NEED_NETDEV,
8211 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8212 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008213 {
8214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308215 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8217 WIPHY_VENDOR_CMD_NEED_NETDEV |
8218 WIPHY_VENDOR_CMD_NEED_RUNNING,
8219 .doit = hdd_cfg80211_get_station_cmd
8220 },
8221 {
8222 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008223 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8224 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8225 WIPHY_VENDOR_CMD_NEED_NETDEV |
8226 WIPHY_VENDOR_CMD_NEED_RUNNING,
8227 .doit = wlan_hdd_cfg80211_do_acs
8228 },
8229
8230 {
8231 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8232 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8233 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8234 WIPHY_VENDOR_CMD_NEED_NETDEV,
8235 .doit = wlan_hdd_cfg80211_get_features
8236 },
8237#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8238 {
8239 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8240 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8241 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8242 WIPHY_VENDOR_CMD_NEED_NETDEV |
8243 WIPHY_VENDOR_CMD_NEED_RUNNING,
8244 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8245 },
8246#endif
8247#ifdef FEATURE_WLAN_EXTSCAN
8248 {
8249 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8250 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8251 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8252 WIPHY_VENDOR_CMD_NEED_NETDEV |
8253 WIPHY_VENDOR_CMD_NEED_RUNNING,
8254 .doit = wlan_hdd_cfg80211_set_passpoint_list
8255 },
8256 {
8257 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8258 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8259 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8260 WIPHY_VENDOR_CMD_NEED_NETDEV |
8261 WIPHY_VENDOR_CMD_NEED_RUNNING,
8262 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8263 },
8264 {
8265 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8266 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8267 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8268 WIPHY_VENDOR_CMD_NEED_NETDEV |
8269 WIPHY_VENDOR_CMD_NEED_RUNNING,
8270 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8271 },
8272 {
8273 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8274 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8275 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8276 WIPHY_VENDOR_CMD_NEED_NETDEV |
8277 WIPHY_VENDOR_CMD_NEED_RUNNING,
8278 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8279 },
8280#endif /* FEATURE_WLAN_EXTSCAN */
8281 {
8282 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8283 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8284 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8285 WIPHY_VENDOR_CMD_NEED_NETDEV,
8286 .doit = wlan_hdd_cfg80211_get_wifi_info
8287 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008288#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008289 {
8290 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8291 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8292 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8293 WIPHY_VENDOR_CMD_NEED_NETDEV |
8294 WIPHY_VENDOR_CMD_NEED_RUNNING,
8295 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8296 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008297#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008298 {
8299 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8300 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8301 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8302 WIPHY_VENDOR_CMD_NEED_NETDEV,
8303 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8304 },
8305 {
8306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8309 WIPHY_VENDOR_CMD_NEED_NETDEV,
8310 .doit = wlan_hdd_cfg80211_wifi_logger_start
8311 },
8312 {
8313 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8314 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8316 WIPHY_VENDOR_CMD_NEED_NETDEV,
8317 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8318 },
8319 {
8320 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8321 .info.subcmd =
8322 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8323 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8324 WIPHY_VENDOR_CMD_NEED_NETDEV |
8325 WIPHY_VENDOR_CMD_NEED_RUNNING,
8326 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8327 },
8328 {
8329 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8330 .info.subcmd =
8331 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8332 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8333 WIPHY_VENDOR_CMD_NEED_NETDEV |
8334 WIPHY_VENDOR_CMD_NEED_RUNNING,
8335 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8336 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008337#ifdef WLAN_FEATURE_TSF
8338 {
8339 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8340 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8341 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8342 WIPHY_VENDOR_CMD_NEED_NETDEV |
8343 WIPHY_VENDOR_CMD_NEED_RUNNING,
8344 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8345 },
8346#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008347#ifdef FEATURE_WLAN_TDLS
8348 {
8349 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8350 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8352 WIPHY_VENDOR_CMD_NEED_NETDEV |
8353 WIPHY_VENDOR_CMD_NEED_RUNNING,
8354 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8355 },
8356#endif
8357#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8358 {
8359 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8360 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8361 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8362 WIPHY_VENDOR_CMD_NEED_NETDEV |
8363 WIPHY_VENDOR_CMD_NEED_RUNNING,
8364 .doit = wlan_hdd_cfg80211_offloaded_packets
8365 },
8366#endif
8367 {
8368 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8369 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8370 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8371 WIPHY_VENDOR_CMD_NEED_NETDEV |
8372 WIPHY_VENDOR_CMD_NEED_RUNNING,
8373 .doit = wlan_hdd_cfg80211_monitor_rssi
8374 },
8375 {
8376 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308377 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8378 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8379 WIPHY_VENDOR_CMD_NEED_NETDEV |
8380 WIPHY_VENDOR_CMD_NEED_RUNNING,
8381 .doit = wlan_hdd_cfg80211_set_ns_offload
8382 },
8383 {
8384 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008385 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8386 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8387 WIPHY_VENDOR_CMD_NEED_NETDEV |
8388 WIPHY_VENDOR_CMD_NEED_RUNNING,
8389 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8390 },
8391#ifdef WLAN_FEATURE_MEMDUMP
8392 {
8393 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8394 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8395 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8396 WIPHY_VENDOR_CMD_NEED_NETDEV |
8397 WIPHY_VENDOR_CMD_NEED_RUNNING,
8398 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8399 },
8400#endif /* WLAN_FEATURE_MEMDUMP */
8401 {
8402 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8403 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8404 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8405 WIPHY_VENDOR_CMD_NEED_NETDEV |
8406 WIPHY_VENDOR_CMD_NEED_RUNNING,
8407 .doit = wlan_hdd_cfg80211_vendor_scan
8408 },
8409
8410 /* OCB commands */
8411 {
8412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8413 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8414 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8415 WIPHY_VENDOR_CMD_NEED_NETDEV |
8416 WIPHY_VENDOR_CMD_NEED_RUNNING,
8417 .doit = wlan_hdd_cfg80211_ocb_set_config
8418 },
8419 {
8420 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8421 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8422 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8423 WIPHY_VENDOR_CMD_NEED_NETDEV |
8424 WIPHY_VENDOR_CMD_NEED_RUNNING,
8425 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8426 },
8427 {
8428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8429 .info.subcmd =
8430 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8431 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8432 WIPHY_VENDOR_CMD_NEED_NETDEV |
8433 WIPHY_VENDOR_CMD_NEED_RUNNING,
8434 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8435 },
8436 {
8437 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8438 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8439 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8440 WIPHY_VENDOR_CMD_NEED_NETDEV |
8441 WIPHY_VENDOR_CMD_NEED_RUNNING,
8442 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8443 },
8444 {
8445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8448 WIPHY_VENDOR_CMD_NEED_NETDEV |
8449 WIPHY_VENDOR_CMD_NEED_RUNNING,
8450 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8451 },
8452 {
8453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8456 WIPHY_VENDOR_CMD_NEED_NETDEV |
8457 WIPHY_VENDOR_CMD_NEED_RUNNING,
8458 .doit = wlan_hdd_cfg80211_dcc_get_stats
8459 },
8460 {
8461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8464 WIPHY_VENDOR_CMD_NEED_NETDEV |
8465 WIPHY_VENDOR_CMD_NEED_RUNNING,
8466 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8467 },
8468 {
8469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8470 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8471 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8472 WIPHY_VENDOR_CMD_NEED_NETDEV |
8473 WIPHY_VENDOR_CMD_NEED_RUNNING,
8474 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8475 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308476 {
8477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8480 WIPHY_VENDOR_CMD_NEED_NETDEV |
8481 WIPHY_VENDOR_CMD_NEED_RUNNING,
8482 .doit = wlan_hdd_cfg80211_get_link_properties
8483 },
Peng Xu278d0122015-09-24 16:34:17 -07008484 {
Peng Xud2220962016-07-11 17:59:17 -07008485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008486 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8487 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8488 WIPHY_VENDOR_CMD_NEED_NETDEV |
8489 WIPHY_VENDOR_CMD_NEED_RUNNING,
8490 .doit = wlan_hdd_cfg80211_set_ota_test
8491 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008492#ifdef FEATURE_LFR_SUBNET_DETECTION
8493 {
8494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8495 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8497 WIPHY_VENDOR_CMD_NEED_NETDEV |
8498 WIPHY_VENDOR_CMD_NEED_RUNNING,
8499 .doit = wlan_hdd_cfg80211_set_gateway_params
8500 },
8501#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008502 {
Peng Xud2220962016-07-11 17:59:17 -07008503 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008504 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8505 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8506 WIPHY_VENDOR_CMD_NEED_NETDEV |
8507 WIPHY_VENDOR_CMD_NEED_RUNNING,
8508 .doit = wlan_hdd_cfg80211_txpower_scale
8509 },
8510 {
8511 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8512 .info.subcmd =
8513 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8514 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8515 WIPHY_VENDOR_CMD_NEED_NETDEV |
8516 WIPHY_VENDOR_CMD_NEED_RUNNING,
8517 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8518 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308519 {
8520 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8521 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8522 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8523 WIPHY_VENDOR_CMD_NEED_NETDEV |
8524 WIPHY_VENDOR_CMD_NEED_RUNNING,
8525 .doit = wlan_hdd_cfg80211_bpf_offload
8526 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308527 {
8528 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308529 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8530 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8531 WIPHY_VENDOR_CMD_NEED_NETDEV |
8532 WIPHY_VENDOR_CMD_NEED_RUNNING,
8533 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8534 },
8535 {
8536 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308537 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8538 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8539 WIPHY_VENDOR_CMD_NEED_NETDEV |
8540 WIPHY_VENDOR_CMD_NEED_RUNNING,
8541 .doit = wlan_hdd_cfg80211_sta_roam_policy
8542 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308543#ifdef FEATURE_WLAN_CH_AVOID
8544 {
8545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8548 WIPHY_VENDOR_CMD_NEED_NETDEV |
8549 WIPHY_VENDOR_CMD_NEED_RUNNING,
8550 .doit = wlan_hdd_cfg80211_avoid_freq
8551 },
8552#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308553 {
8554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308555 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8556 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8557 WIPHY_VENDOR_CMD_NEED_NETDEV |
8558 WIPHY_VENDOR_CMD_NEED_RUNNING,
8559 .doit = wlan_hdd_cfg80211_sap_configuration_set
8560 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008561 {
Peng Xu4225c152016-07-14 21:18:14 -07008562 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008563 .info.subcmd =
8564 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8565 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8566 WIPHY_VENDOR_CMD_NEED_NETDEV |
8567 WIPHY_VENDOR_CMD_NEED_RUNNING,
8568 .doit = wlan_hdd_cfg80211_p2p_lo_start
8569 },
8570 {
8571 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8572 .info.subcmd =
8573 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8574 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8575 WIPHY_VENDOR_CMD_NEED_NETDEV |
8576 WIPHY_VENDOR_CMD_NEED_RUNNING,
8577 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8578 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308579 {
8580 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8581 .info.subcmd =
8582 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8583 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8584 WIPHY_VENDOR_CMD_NEED_NETDEV |
8585 WIPHY_VENDOR_CMD_NEED_RUNNING,
8586 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8587 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008588#ifdef WLAN_FEATURE_NAN_DATAPATH
8589 {
8590 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8591 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8592 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8593 WIPHY_VENDOR_CMD_NEED_NETDEV |
8594 WIPHY_VENDOR_CMD_NEED_RUNNING,
8595 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8596 },
8597#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308598 {
8599 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8600 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8601 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8602 WIPHY_VENDOR_CMD_NEED_NETDEV |
8603 WIPHY_VENDOR_CMD_NEED_RUNNING,
8604 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8605 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308606 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308607 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8608 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8609 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8610 WIPHY_VENDOR_CMD_NEED_NETDEV |
8611 WIPHY_VENDOR_CMD_NEED_RUNNING,
8612 .doit = wlan_hdd_cfg80211_get_bus_size
8613 },
8614 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8617 WIPHY_VENDOR_CMD_NEED_NETDEV |
8618 WIPHY_VENDOR_CMD_NEED_RUNNING,
8619 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308620 },
8621 {
8622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8625 WIPHY_VENDOR_CMD_NEED_NETDEV |
8626 WIPHY_VENDOR_CMD_NEED_RUNNING,
8627 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308628 },
8629#ifdef WLAN_FEATURE_DISA
8630 {
8631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8632 .info.subcmd =
8633 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8634 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8635 WIPHY_VENDOR_CMD_NEED_NETDEV |
8636 WIPHY_VENDOR_CMD_NEED_RUNNING,
8637 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8638 },
8639#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008640#ifdef FEATURE_WLAN_TDLS
8641 {
8642 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8643 .info.subcmd =
8644 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8646 WIPHY_VENDOR_CMD_NEED_NETDEV |
8647 WIPHY_VENDOR_CMD_NEED_RUNNING,
8648 .doit = wlan_hdd_cfg80211_configure_tdls_mode
8649 }
8650#endif
Paul Zhang3a210c52016-12-08 10:18:12 +08008651#ifdef WLAN_UMAC_CONVERGENCE
8652 COMMON_VENDOR_COMMANDS
8653#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008654};
8655
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008656/**
8657 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8658 * @priv_size: Size of the hdd context.
8659 *
8660 * Allocate wiphy context and hdd context.
8661 *
8662 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008663 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008664hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008665{
8666 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008667 hdd_context_t *hdd_ctx;
8668
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008669 ENTER();
8670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8672
8673 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008674 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008675 return NULL;
8676 }
8677
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008678 hdd_ctx = wiphy_priv(wiphy);
8679
8680 hdd_ctx->wiphy = wiphy;
8681
8682 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008683}
8684
8685/*
8686 * FUNCTION: wlan_hdd_cfg80211_update_band
8687 * This function is called from the supplicant through a
8688 * private ioctl to change the band value
8689 */
8690int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8691{
8692 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008693 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008694
8695 ENTER();
8696
Dustin Browna30892e2016-10-12 17:28:36 -07008697 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008698
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008699 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008700 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008701
8702 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8703 struct ieee80211_supported_band *band = wiphy->bands[i];
8704
8705 channelEnabledState =
8706 cds_get_channel_state(band->channels[j].
8707 hw_value);
8708
Dustin Browna30892e2016-10-12 17:28:36 -07008709 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008710 /* 5G only */
8711#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8712 /* Enable Social channels for P2P */
8713 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8714 (band->channels[j].center_freq)
8715 && CHANNEL_STATE_ENABLE ==
8716 channelEnabledState)
8717 band->channels[j].flags &=
8718 ~IEEE80211_CHAN_DISABLED;
8719 else
8720#endif
8721 band->channels[j].flags |=
8722 IEEE80211_CHAN_DISABLED;
8723 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008724 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008725 eCSR_BAND_24 == eBand) {
8726 /* 2G only */
8727 band->channels[j].flags |=
8728 IEEE80211_CHAN_DISABLED;
8729 continue;
8730 }
8731
Amar Singhal6842e8f2016-02-23 16:30:32 -08008732 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008733 band->channels[j].flags &=
8734 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 }
8736 }
8737 return 0;
8738}
8739
8740/*
8741 * FUNCTION: wlan_hdd_cfg80211_init
8742 * This function is called by hdd_wlan_startup()
8743 * during initialization.
8744 * This function is used to initialize and register wiphy structure.
8745 */
8746int wlan_hdd_cfg80211_init(struct device *dev,
8747 struct wiphy *wiphy, struct hdd_config *pCfg)
8748{
8749 int i, j;
8750 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8751
8752 ENTER();
8753
8754 /* Now bind the underlying wlan device with wiphy */
8755 set_wiphy_dev(wiphy, dev);
8756
8757 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008759#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8760 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008761 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008762#else
8763 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008764 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008765#endif
8766
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008767 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8768 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8769 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8770#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8771 | WIPHY_FLAG_4ADDR_STATION
8772#endif
8773 | WIPHY_FLAG_OFFCHAN_TX;
8774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008775#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8776 wiphy->wowlan = &wowlan_support_cfg80211_init;
8777#else
8778 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8779 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8780 wiphy->wowlan.pattern_min_len = 1;
8781 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8782#endif
8783
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008784 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008785#ifdef FEATURE_WLAN_ESE
8786 || pCfg->isEseIniFeatureEnabled
8787#endif
8788 ) {
8789 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8790 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008791#ifdef FEATURE_WLAN_TDLS
8792 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8793 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8794#endif
8795
8796 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8797
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008798#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8799 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8800#endif
8801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008802#ifdef FEATURE_WLAN_SCAN_PNO
8803 if (pCfg->configPNOScanSupport) {
8804 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8805 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8806 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8807 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008808#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8809 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8810#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008811 }
8812#endif /*FEATURE_WLAN_SCAN_PNO */
8813
8814#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308815 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008816#endif
8817
8818 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8819 driver can still register regulatory callback and
8820 it will get regulatory settings in wiphy->band[], but
8821 driver need to determine what to do with both
8822 regulatory settings */
8823
8824 wiphy->reg_notifier = hdd_reg_notifier;
8825
8826#if defined QCA_WIFI_FTM
8827}
8828#endif
8829
8830 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8831
8832 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8833
8834 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8835
Arun Khandavallifae92942016-08-01 13:31:08 +05308836 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8837 | BIT(NL80211_IFTYPE_ADHOC)
8838 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8839 | BIT(NL80211_IFTYPE_P2P_GO)
8840 | BIT(NL80211_IFTYPE_AP)
8841 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008842
Arun Khandavallifae92942016-08-01 13:31:08 +05308843 if (pCfg->advertiseConcurrentOperation) {
8844 if (pCfg->enableMCC) {
8845 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008846
Arun Khandavallifae92942016-08-01 13:31:08 +05308847 for (i = 0;
8848 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8849 i++) {
8850 if (!pCfg->allowMCCGODiffBI)
8851 wlan_hdd_iface_combination[i].
8852 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008853 }
8854 }
8855 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308856 ARRAY_SIZE(wlan_hdd_iface_combination);
8857 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008858 }
8859
8860 /* Before registering we need to update the ht capabilitied based
8861 * on ini values*/
8862 if (!pCfg->ShortGI20MhzEnable) {
8863 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8864 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008865 }
8866
8867 if (!pCfg->ShortGI40MhzEnable) {
8868 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8869 }
8870
8871 if (!pCfg->nChannelBondingMode5GHz) {
8872 wlan_hdd_band_5_ghz.ht_cap.cap &=
8873 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8874 }
8875
Abhishek Singhf512bf32016-05-04 16:47:46 +05308876 /*
8877 * In case of static linked driver at the time of driver unload,
8878 * module exit doesn't happens. Module cleanup helps in cleaning
8879 * of static memory.
8880 * If driver load happens statically, at the time of driver unload,
8881 * wiphy flags don't get reset because of static memory.
8882 * It's better not to store channel in static memory.
8883 */
Dustin Browna30892e2016-10-12 17:28:36 -07008884 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8885 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308886 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008887 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308888 hdd_err("Not enough memory to allocate channels");
8889 return -ENOMEM;
8890 }
Dustin Browna30892e2016-10-12 17:28:36 -07008891 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308892 &hdd_channels_2_4_ghz[0],
8893 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308894 if ((hdd_is_5g_supported(pHddCtx)) &&
8895 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8896 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8897 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8898 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008899 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8900 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308901 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008902 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308903 hdd_err("Not enough memory to allocate channels");
8904 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008905 bands[NL80211_BAND_2GHZ]->channels);
8906 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308907 return -ENOMEM;
8908 }
Dustin Browna30892e2016-10-12 17:28:36 -07008909 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308910 &hdd_channels_5_ghz[0],
8911 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008912 }
8913
Dustin Browna30892e2016-10-12 17:28:36 -07008914 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008915
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008916 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008917 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008918
8919 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8920 struct ieee80211_supported_band *band = wiphy->bands[i];
8921
Dustin Browna30892e2016-10-12 17:28:36 -07008922 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008923 eCSR_BAND_5G == pCfg->nBandCapability) {
8924 /* 5G only */
8925#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8926 /* Enable social channels for P2P */
8927 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8928 (band->channels[j].center_freq))
8929 band->channels[j].flags &=
8930 ~IEEE80211_CHAN_DISABLED;
8931 else
8932#endif
8933 band->channels[j].flags |=
8934 IEEE80211_CHAN_DISABLED;
8935 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008936 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008937 eCSR_BAND_24 == pCfg->nBandCapability) {
8938 /* 2G only */
8939 band->channels[j].flags |=
8940 IEEE80211_CHAN_DISABLED;
8941 continue;
8942 }
8943 }
8944 }
8945 /*Initialise the supported cipher suite details */
8946 wiphy->cipher_suites = hdd_cipher_suites;
8947 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8948
8949 /*signal strength in mBm (100*dBm) */
8950 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8951 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8952
Anurag Chouhan6d760662016-02-20 16:05:43 +05308953 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008954 wiphy->n_vendor_commands =
8955 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8956 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8957
8958 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8959 wiphy->n_vendor_events =
8960 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8961 }
8962
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008963 if (pCfg->enableDFSMasterCap) {
8964 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8965 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008966
8967 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8968
8969#ifdef QCA_HT_2040_COEX
8970 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8971#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05308972 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308973 hdd_add_channel_switch_support(&wiphy->flags);
8974
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008975 EXIT();
8976 return 0;
8977}
8978
Abhishek Singhf512bf32016-05-04 16:47:46 +05308979/**
Yingying Tang80e15f32016-09-27 18:23:01 +08008980 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
8981 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05308982 *
8983 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308984 * memory allocated in wlan_hdd_cfg80211_init also
8985 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308986 *
8987 * Return: void
8988 */
8989void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8990{
8991 int i;
8992
Dustin Browna30892e2016-10-12 17:28:36 -07008993 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308994 if (NULL != wiphy->bands[i] &&
8995 (NULL != wiphy->bands[i]->channels)) {
8996 qdf_mem_free(wiphy->bands[i]->channels);
8997 wiphy->bands[i]->channels = NULL;
8998 }
8999 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309000 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309001}
9002
Yingying Tang80e15f32016-09-27 18:23:01 +08009003/**
9004 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9005 * @hdd_ctx: HDD context
9006 *
9007 * this function will update capabilities for supported bands
9008 *
9009 * Return: void
9010 */
9011static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9012{
9013 uint32_t val32;
9014 uint16_t val16;
9015 tSirMacHTCapabilityInfo *ht_cap_info;
9016 QDF_STATUS status;
9017
9018 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9019 if (QDF_STATUS_SUCCESS != status) {
9020 hdd_err("could not get HT capability info");
9021 val32 = 0;
9022 }
9023 val16 = (uint16_t)val32;
9024 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9025
9026 if (ht_cap_info->txSTBC == true) {
9027 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9028 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9029 IEEE80211_HT_CAP_TX_STBC;
9030 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9031 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9032 IEEE80211_HT_CAP_TX_STBC;
9033 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009034
9035 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9036 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9037 vht_cap.vht_supported = 0;
9038 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9039 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9040 vht_cap.vht_supported = 0;
9041 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9042 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009043}
9044
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009045/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309046 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009047 * initialization. In wlan_hdd_cfg80211_init, only the
9048 * default values will be initialized. The final initialization
9049 * of all required members can be done here.
9050 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009051void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009052{
Yingying Tang80e15f32016-09-27 18:23:01 +08009053 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9054
9055 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009056}
9057
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009058/**
9059 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9060 * @cfg: hdd cfg
9061 *
9062 * this function update 11n mode in hdd cfg
9063 *
9064 * Return: void
9065 */
9066void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9067{
9068 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9069 hdd_notice("support 11ac");
9070 } else {
9071 hdd_notice("not support 11ac");
9072 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9073 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9074 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9075 cfg->sap_p2p_11ac_override = 0;
9076 }
9077 }
9078}
9079
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009080/* In this function we are registering wiphy. */
9081int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9082{
9083 ENTER();
9084 /* Register our wiphy dev with cfg80211 */
9085 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009086 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009087 return -EIO;
9088 }
9089
9090 EXIT();
9091 return 0;
9092}
9093
9094/*
9095 HDD function to update wiphy capability based on target offload status.
9096
9097 wlan_hdd_cfg80211_init() does initialization of all wiphy related
9098 capability even before downloading firmware to the target. In discrete
9099 case, host will get know certain offload capability (say sched_scan
9100 caps) only after downloading firmware to the target and target boots up.
9101 This function is used to override setting done in wlan_hdd_cfg80211_init()
9102 based on target capability.
9103 */
9104void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9105{
9106#ifdef FEATURE_WLAN_SCAN_PNO
9107 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9108 struct hdd_config *pCfg = pHddCtx->config;
9109
9110 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9111 * control comes here. Here just we need to clear it if firmware doesn't
9112 * have PNO support. */
9113 if (!pCfg->PnoOffload) {
9114 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9115 wiphy->max_sched_scan_ssids = 0;
9116 wiphy->max_match_sets = 0;
9117 wiphy->max_sched_scan_ie_len = 0;
9118 }
9119#endif
9120}
9121
9122/* This function registers for all frame which supplicant is interested in */
9123void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9124{
9125 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9126 /* Register for all P2P action, public action etc frames */
9127 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9128
9129 ENTER();
9130
Abhishek Singh7996eb72015-12-30 17:24:02 +05309131 /* Register frame indication call back */
9132 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9133
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309134 /* Register for p2p ack indication */
9135 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137 /* Right now we are registering these frame when driver is getting
9138 initialized. Once we will move to 2.6.37 kernel, in which we have
9139 frame register ops, we will move this code as a part of that */
9140 /* GAS Initial Request */
9141 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9142 (uint8_t *) GAS_INITIAL_REQ,
9143 GAS_INITIAL_REQ_SIZE);
9144
9145 /* GAS Initial Response */
9146 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9147 (uint8_t *) GAS_INITIAL_RSP,
9148 GAS_INITIAL_RSP_SIZE);
9149
9150 /* GAS Comeback Request */
9151 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9152 (uint8_t *) GAS_COMEBACK_REQ,
9153 GAS_COMEBACK_REQ_SIZE);
9154
9155 /* GAS Comeback Response */
9156 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9157 (uint8_t *) GAS_COMEBACK_RSP,
9158 GAS_COMEBACK_RSP_SIZE);
9159
9160 /* P2P Public Action */
9161 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9162 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9163 P2P_PUBLIC_ACTION_FRAME_SIZE);
9164
9165 /* P2P Action */
9166 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9167 (uint8_t *) P2P_ACTION_FRAME,
9168 P2P_ACTION_FRAME_SIZE);
9169
9170 /* WNM BSS Transition Request frame */
9171 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9172 (uint8_t *) WNM_BSS_ACTION_FRAME,
9173 WNM_BSS_ACTION_FRAME_SIZE);
9174
9175 /* WNM-Notification */
9176 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9177 (uint8_t *) WNM_NOTIFICATION_FRAME,
9178 WNM_NOTIFICATION_FRAME_SIZE);
9179}
9180
9181void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9182{
9183 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9184 /* Register for all P2P action, public action etc frames */
9185 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9186
9187 ENTER();
9188
9189 /* Right now we are registering these frame when driver is getting
9190 initialized. Once we will move to 2.6.37 kernel, in which we have
9191 frame register ops, we will move this code as a part of that */
9192 /* GAS Initial Request */
9193
9194 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9195 (uint8_t *) GAS_INITIAL_REQ,
9196 GAS_INITIAL_REQ_SIZE);
9197
9198 /* GAS Initial Response */
9199 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9200 (uint8_t *) GAS_INITIAL_RSP,
9201 GAS_INITIAL_RSP_SIZE);
9202
9203 /* GAS Comeback Request */
9204 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9205 (uint8_t *) GAS_COMEBACK_REQ,
9206 GAS_COMEBACK_REQ_SIZE);
9207
9208 /* GAS Comeback Response */
9209 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9210 (uint8_t *) GAS_COMEBACK_RSP,
9211 GAS_COMEBACK_RSP_SIZE);
9212
9213 /* P2P Public Action */
9214 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9215 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9216 P2P_PUBLIC_ACTION_FRAME_SIZE);
9217
9218 /* P2P Action */
9219 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9220 (uint8_t *) P2P_ACTION_FRAME,
9221 P2P_ACTION_FRAME_SIZE);
9222
9223 /* WNM-Notification */
9224 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9225 (uint8_t *) WNM_NOTIFICATION_FRAME,
9226 WNM_NOTIFICATION_FRAME_SIZE);
9227}
9228
9229#ifdef FEATURE_WLAN_WAPI
9230void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9231 const uint8_t *mac_addr, const uint8_t *key,
9232 int key_Len)
9233{
9234 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9235 tCsrRoamSetKey setKey;
9236 bool isConnected = true;
9237 int status = 0;
9238 uint32_t roamId = 0xFF;
9239 uint8_t *pKeyPtr = NULL;
9240 int n = 0;
9241
Jeff Johnson46b40792016-06-29 14:03:14 -07009242 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009243 hdd_device_mode_to_string(pAdapter->device_mode),
9244 pAdapter->device_mode);
9245
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309246 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009247 setKey.keyId = key_index; /* Store Key ID */
9248 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9249 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9250 setKey.paeRole = 0; /* the PAE role */
9251 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309252 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309254 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009255 }
9256 setKey.keyLength = key_Len;
9257 pKeyPtr = setKey.Key;
9258 memcpy(pKeyPtr, key, key_Len);
9259
Jeff Johnson46b40792016-06-29 14:03:14 -07009260 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009261 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009262 hdd_notice("WAPI KEY Data[%d]:%02x ",
9263 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264
9265 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9266 if (isConnected) {
9267 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9268 pAdapter->sessionId, &setKey, &roamId);
9269 }
9270 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009271 hdd_err("sme_roam_set_key returned ERROR status= %d",
9272 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009273 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9274 }
9275}
9276#endif /* FEATURE_WLAN_WAPI */
9277
9278uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9279 uint8_t eid)
9280{
9281 int left = length;
9282 uint8_t *ptr = (uint8_t *)ies_ptr;
9283 uint8_t elem_id, elem_len;
9284
9285 while (left >= 2) {
9286 elem_id = ptr[0];
9287 elem_len = ptr[1];
9288 left -= 2;
9289 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009290 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009291 eid, elem_len, left);
9292 return NULL;
9293 }
9294 if (elem_id == eid) {
9295 return ptr;
9296 }
9297
9298 left -= elem_len;
9299 ptr += (elem_len + 2);
9300 }
9301 return NULL;
9302}
9303
9304/*
9305 * FUNCTION: wlan_hdd_validate_operation_channel
9306 * called by wlan_hdd_cfg80211_start_bss() and
9307 * wlan_hdd_set_channel()
9308 * This function validates whether given channel is part of valid
9309 * channel list.
9310 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309311QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009312 int channel)
9313{
9314
9315 uint32_t num_ch = 0;
9316 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9317 u32 indx = 0;
9318 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9319 uint8_t fValidChannel = false, count = 0;
9320 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9321
9322 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9323
9324 if (hdd_pConfig_ini->sapAllowAllChannel) {
9325 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009326 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009327 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009328 fValidChannel = true;
9329 break;
9330 }
9331 }
9332 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009333 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309334 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009335 }
9336 } else {
9337 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9338 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009339 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309340 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009341 }
9342 for (indx = 0; indx < num_ch; indx++) {
9343 if (channel == valid_ch[indx]) {
9344 break;
9345 }
9346 }
9347
9348 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009349 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309350 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009351 }
9352 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309353 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009354
9355}
9356
9357#ifdef DHCP_SERVER_OFFLOAD
9358static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9359{
9360 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9361 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9362 uint8_t numEntries = 0;
9363 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9364 uint8_t num;
9365 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309366 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009367 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009368 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009369 return;
9370 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009371 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9372 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9373 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9374 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9375 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9376 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009377 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009378 goto end;
9379 }
9380 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009381 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382 goto end;
9383 }
9384 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009385 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009386 goto end;
9387 }
9388 for (num = 0; num < numEntries; num++) {
9389 temp = srv_ip[num];
9390 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9391 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309392 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009393 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009394 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009395 goto end;
9396 }
Jeff Johnson77848112016-06-29 14:52:06 -07009397 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309399 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400 return;
9401}
9402#endif /* DHCP_SERVER_OFFLOAD */
9403
9404static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9405 struct net_device *dev,
9406 struct bss_parameters *params)
9407{
9408 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9409 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9410 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309411 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009412
9413 ENTER();
9414
Anurag Chouhan6d760662016-02-20 16:05:43 +05309415 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009416 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 return -EINVAL;
9418 }
9419
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309420 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9421 hdd_err("invalid session id: %d", pAdapter->sessionId);
9422 return -EINVAL;
9423 }
9424
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309425 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9427 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009428 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429 hdd_device_mode_to_string(pAdapter->device_mode),
9430 pAdapter->device_mode, params->ap_isolate);
9431
9432 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9433 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309434 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009436
Krunal Sonib4326f22016-03-10 13:05:51 -08009437 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9438 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009439 return -EOPNOTSUPP;
9440 }
9441
9442 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9443 * want to update this parameter */
9444 if (-1 != params->ap_isolate) {
9445 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9446 !!params->ap_isolate;
9447
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309448 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009449 pAdapter->sessionId,
9450 pAdapter->sessionCtx.
9451 ap.
9452 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309453 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454 ret = -EINVAL;
9455 }
9456 }
9457
9458 EXIT();
9459 return ret;
9460}
9461
Krunal Soni8c37e322016-02-03 16:08:37 -08009462/**
9463 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9464 * @ndev: pointer to net device provided by supplicant
9465 * @type: type of the interface, upper layer wanted to change
9466 *
9467 * Upper layer provides the new interface mode that needs to be changed
9468 * for given net device
9469 *
9470 * Return: success or failure in terms of integer value
9471 */
9472static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473 enum nl80211_iftype type)
9474{
Krunal Soni8c37e322016-02-03 16:08:37 -08009475 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9476 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9477 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009478 hdd_wext_state_t *wext;
9479 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309480 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009481
9482 ENTER();
9483
Krunal Soni8c37e322016-02-03 16:08:37 -08009484 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009485 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009486 return 0;
9487 }
9488
9489 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009490 hdd_stop_adapter(hdd_ctx, adapter, true);
9491 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009492 wdev->iftype = type;
9493 /*Check for sub-string p2p to confirm its a p2p interface */
9494 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009495 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009497 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009498 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009499 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009500 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009501 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009502 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009503 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009505 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9506 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009507 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9508 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009509 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009510 adapter->scan_info.scanAddIE.length;
9511 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309512 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009513 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9514 wext->roamProfile.phyMode =
9515 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9516 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009517 EXIT();
9518 return status;
9519}
9520
9521static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9522 struct net_device *dev,
9523 struct bss_parameters *params)
9524{
9525 int ret;
9526
9527 cds_ssr_protect(__func__);
9528 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9529 cds_ssr_unprotect(__func__);
9530
9531 return ret;
9532}
9533
9534/* FUNCTION: wlan_hdd_change_country_code_cd
9535 * to wait for contry code completion
9536 */
9537void *wlan_hdd_change_country_code_cb(void *pAdapter)
9538{
9539 hdd_adapter_t *call_back_pAdapter = pAdapter;
9540 complete(&call_back_pAdapter->change_country_code);
9541 return NULL;
9542}
9543
Rajeev Kumar98edb772016-01-19 12:42:19 -08009544/**
9545 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9546 * @wiphy: Pointer to the wiphy structure
9547 * @ndev: Pointer to the net device
9548 * @type: Interface type
9549 * @flags: Flags for change interface
9550 * @params: Pointer to change interface parameters
9551 *
9552 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553 */
9554static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9555 struct net_device *ndev,
9556 enum nl80211_iftype type,
9557 u32 *flags,
9558 struct vif_params *params)
9559{
9560 struct wireless_dev *wdev;
9561 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9562 hdd_context_t *pHddCtx;
9563 tCsrRoamProfile *pRoamProfile = NULL;
9564 eCsrRoamBssType LastBSSType;
9565 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309566 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567 int status;
9568
9569 ENTER();
9570
Anurag Chouhan6d760662016-02-20 16:05:43 +05309571 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009572 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009573 return -EINVAL;
9574 }
9575
9576 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9577 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309578 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009579 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309581 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009582 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9583 pAdapter->sessionId, type));
9584
Jeff Johnson77848112016-06-29 14:52:06 -07009585 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586 pAdapter->device_mode, type);
9587
Arun Khandavallifae92942016-08-01 13:31:08 +05309588 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9589 if (status) {
9590 hdd_err("Failed to start modules");
9591 return -EINVAL;
9592 }
9593
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009594 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9596 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009597 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009598 return -EINVAL;
9599 }
9600
9601 pConfig = pHddCtx->config;
9602 wdev = ndev->ieee80211_ptr;
9603
9604 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009605 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009606
9607 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9608
Krunal Sonib4326f22016-03-10 13:05:51 -08009609 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9610 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9611 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9612 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009613 hdd_wext_state_t *pWextState =
9614 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9615
9616 pRoamProfile = &pWextState->roamProfile;
9617 LastBSSType = pRoamProfile->BSSType;
9618
9619 switch (type) {
9620 case NL80211_IFTYPE_STATION:
9621 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009622 case NL80211_IFTYPE_ADHOC:
9623 if (type == NL80211_IFTYPE_ADHOC) {
9624 wlan_hdd_tdls_exit(pAdapter);
9625 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009626 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009627 }
9628 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9629 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309630 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009631 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309632 if (hdd_start_adapter(pAdapter)) {
9633 hdd_err("Failed to start adapter :%d",
9634 pAdapter->device_mode);
9635 return -EINVAL;
9636 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009638 case NL80211_IFTYPE_AP:
9639 case NL80211_IFTYPE_P2P_GO:
9640 {
Jeff Johnson77848112016-06-29 14:52:06 -07009641 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 (type ==
9643 NL80211_IFTYPE_AP) ? "SoftAP" :
9644 "P2pGo");
9645
9646 /* Cancel any remain on channel for GO mode */
9647 if (NL80211_IFTYPE_P2P_GO == type) {
9648 wlan_hdd_cancel_existing_remain_on_channel
9649 (pAdapter);
9650 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009651
Arun Khandavallifae92942016-08-01 13:31:08 +05309652 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009653 /* De-init the adapter */
9654 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9655 memset(&pAdapter->sessionCtx, 0,
9656 sizeof(pAdapter->sessionCtx));
9657 pAdapter->device_mode =
9658 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009659 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9660 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009661
9662 /*
9663 * Fw will take care incase of concurrency
9664 */
9665
Krunal Sonib4326f22016-03-10 13:05:51 -08009666 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 && (pConfig->apRandomBssidEnabled)) {
9668 /* To meet Android requirements create a randomized
9669 MAC address of the form 02:1A:11:Fx:xx:xx */
9670 get_random_bytes(&ndev->dev_addr[3], 3);
9671 ndev->dev_addr[0] = 0x02;
9672 ndev->dev_addr[1] = 0x1A;
9673 ndev->dev_addr[2] = 0x11;
9674 ndev->dev_addr[3] |= 0xF0;
9675 memcpy(pAdapter->macAddressCurrent.
9676 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309677 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678 pr_info("wlan: Generated HotSpot BSSID "
9679 MAC_ADDRESS_STR "\n",
9680 MAC_ADDR_ARRAY(ndev->dev_addr));
9681 }
9682
9683 hdd_set_ap_ops(pAdapter->dev);
9684
Arun Khandavallifae92942016-08-01 13:31:08 +05309685 if (hdd_start_adapter(pAdapter)) {
9686 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009687 return -EINVAL;
9688 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009689 /* Interface type changed update in wiphy structure */
9690 if (wdev) {
9691 wdev->iftype = type;
9692 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009693 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694 return -EINVAL;
9695 }
9696 goto done;
9697 }
9698
9699 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009700 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701 type);
9702 return -EOPNOTSUPP;
9703 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009704 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9705 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009706 switch (type) {
9707 case NL80211_IFTYPE_STATION:
9708 case NL80211_IFTYPE_P2P_CLIENT:
9709 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009710 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9711 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309712 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009713 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309714 if (hdd_start_adapter(pAdapter)) {
9715 hdd_err("Failed to start adapter :%d",
9716 pAdapter->device_mode);
9717 return -EINVAL;
9718 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009719 goto done;
9720
9721 case NL80211_IFTYPE_AP:
9722 case NL80211_IFTYPE_P2P_GO:
9723 wdev->iftype = type;
9724 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009725 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009726 goto done;
9727
9728 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009729 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009730 type);
9731 return -EOPNOTSUPP;
9732 }
9733 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009734 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009735 pAdapter->device_mode);
9736 return -EOPNOTSUPP;
9737 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009738done:
9739 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009740 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009741
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009742 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743
9744 EXIT();
9745 return 0;
9746}
9747
Rajeev Kumar98edb772016-01-19 12:42:19 -08009748/**
9749 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9750 * @wiphy: Pointer to the wiphy structure
9751 * @ndev: Pointer to the net device
9752 * @type: Interface type
9753 * @flags: Flags for change interface
9754 * @params: Pointer to change interface parameters
9755 *
9756 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009757 */
9758static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9759 struct net_device *ndev,
9760 enum nl80211_iftype type,
9761 u32 *flags,
9762 struct vif_params *params)
9763{
9764 int ret;
9765
9766 cds_ssr_protect(__func__);
9767 ret =
9768 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9769 cds_ssr_unprotect(__func__);
9770
9771 return ret;
9772}
9773
9774#ifdef FEATURE_WLAN_TDLS
9775static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9776 int index, uint8_t match)
9777{
9778 int i;
9779 for (i = 0; i < index; i++) {
9780 if (arr[i] == match)
9781 return true;
9782 }
9783 return false;
9784}
9785#endif
9786
9787/**
9788 * __wlan_hdd_change_station() - change station
9789 * @wiphy: Pointer to the wiphy structure
9790 * @dev: Pointer to the net device.
9791 * @mac: bssid
9792 * @params: Pointer to station parameters
9793 *
9794 * Return: 0 for success, error number on failure.
9795 */
9796#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9797static int __wlan_hdd_change_station(struct wiphy *wiphy,
9798 struct net_device *dev,
9799 const uint8_t *mac,
9800 struct station_parameters *params)
9801#else
9802static int __wlan_hdd_change_station(struct wiphy *wiphy,
9803 struct net_device *dev,
9804 uint8_t *mac,
9805 struct station_parameters *params)
9806#endif
9807{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309808 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009809 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9810 hdd_context_t *pHddCtx;
9811 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309812 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009813#ifdef FEATURE_WLAN_TDLS
9814 tCsrStaParams StaParams = { 0 };
9815 uint8_t isBufSta = 0;
9816 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309817 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818#endif
9819 int ret;
9820
9821 ENTER();
9822
Anurag Chouhan6d760662016-02-20 16:05:43 +05309823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009824 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009825 return -EINVAL;
9826 }
9827
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309828 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009829 TRACE_CODE_HDD_CHANGE_STATION,
9830 pAdapter->sessionId, params->listen_interval));
9831
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309832 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9833 hdd_err("invalid session id: %d", pAdapter->sessionId);
9834 return -EINVAL;
9835 }
9836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009837 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9838 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309839 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009840 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009841
9842 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9843
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309844 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009845
Krunal Sonib4326f22016-03-10 13:05:51 -08009846 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9847 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009848 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9849 status =
9850 hdd_softap_change_sta_state(pAdapter,
9851 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009852 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009853
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309854 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009855 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009856 return -EINVAL;
9857 }
9858 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009859 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9860 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009861#ifdef FEATURE_WLAN_TDLS
9862 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009863
9864 if (cds_is_sub_20_mhz_enabled()) {
9865 hdd_err("TDLS not allowed with sub 20 MHz");
9866 return -EINVAL;
9867 }
9868
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869 StaParams.capability = params->capability;
9870 StaParams.uapsd_queues = params->uapsd_queues;
9871 StaParams.max_sp = params->max_sp;
9872
9873 /* Convert (first channel , number of channels) tuple to
9874 * the total list of channels. This goes with the assumption
9875 * that if the first channel is < 14, then the next channels
9876 * are an incremental of 1 else an incremental of 4 till the number
9877 * of channels.
9878 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009879 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009880 if (0 != params->supported_channels_len) {
9881 int i = 0, j = 0, k = 0, no_of_channels = 0;
9882 int num_unique_channels;
9883 int next;
9884 for (i = 0;
9885 i < params->supported_channels_len
9886 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9887 int wifi_chan_index;
9888 if (!wlan_hdd_is_duplicate_channel
9889 (StaParams.supported_channels, j,
9890 params->supported_channels[i])) {
9891 StaParams.
9892 supported_channels[j] =
9893 params->
9894 supported_channels[i];
9895 } else {
9896 continue;
9897 }
9898 wifi_chan_index =
9899 ((StaParams.supported_channels[j] <=
9900 HDD_CHANNEL_14) ? 1 : 4);
9901 no_of_channels =
9902 params->supported_channels[i + 1];
9903
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009904 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 -08009905 StaParams.
9906 supported_channels[j],
9907 wifi_chan_index,
9908 no_of_channels);
9909 for (k = 1; k <= no_of_channels &&
9910 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9911 k++) {
9912 next =
9913 StaParams.
9914 supported_channels[j] +
9915 wifi_chan_index;
9916 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9917 StaParams.
9918 supported_channels[j
9919 +
9920 1]
9921 = next;
9922 } else {
9923 continue;
9924 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009925 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 j + 1,
9927 StaParams.
9928 supported_channels[j +
9929 1]);
9930 j += 1;
9931 }
9932 }
9933 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009934 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009935 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009936 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009937 StaParams.
9938 supported_channels[i]);
9939 }
9940 if (MAX_CHANNEL < num_unique_channels)
9941 num_unique_channels = MAX_CHANNEL;
9942 StaParams.supported_channels_len =
9943 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009944 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009945 StaParams.supported_channels_len);
9946 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309947 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009948 params->supported_oper_classes,
9949 params->supported_oper_classes_len);
9950 StaParams.supported_oper_classes_len =
9951 params->supported_oper_classes_len;
9952
9953 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309954 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009955 params->ext_capab,
9956 sizeof(StaParams.extn_capability));
9957
9958 if (NULL != params->ht_capa) {
9959 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309960 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961 sizeof(tSirHTCap));
9962 }
9963
9964 StaParams.supported_rates_len =
9965 params->supported_rates_len;
9966
9967 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9968 * The supported_rates array , for all the structures propogating till Add Sta
9969 * to the firmware has to be modified , if the supplicant (ieee80211) is
9970 * modified to send more rates.
9971 */
9972
9973 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9974 */
9975 if (StaParams.supported_rates_len >
9976 SIR_MAC_MAX_SUPP_RATES)
9977 StaParams.supported_rates_len =
9978 SIR_MAC_MAX_SUPP_RATES;
9979
9980 if (0 != StaParams.supported_rates_len) {
9981 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309982 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009983 params->supported_rates,
9984 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009985 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 StaParams.supported_rates_len);
9987 for (i = 0; i < StaParams.supported_rates_len;
9988 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009989 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 StaParams.supported_rates[i]);
9991 }
9992
9993 if (NULL != params->vht_capa) {
9994 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309995 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996 params->vht_capa,
9997 sizeof(tSirVHTCap));
9998 }
9999
10000 if (0 != params->ext_capab_len) {
10001 /*Define A Macro : TODO Sunil */
10002 if ((1 << 4) & StaParams.extn_capability[3]) {
10003 isBufSta = 1;
10004 }
10005 /* TDLS Channel Switching Support */
10006 if ((1 << 6) & StaParams.extn_capability[3]) {
10007 isOffChannelSupported = 1;
10008 }
10009 }
10010
Nitesh Shah99934ac2016-09-05 15:54:08 +053010011 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010012 (params->ht_capa || params->vht_capa ||
10013 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010014 is_qos_wmm_sta = true;
10015
10016 hdd_notice("%s: TDLS Peer is QOS capable"
10017 " is_qos_wmm_sta= %d HTcapPresent = %d",
10018 __func__, is_qos_wmm_sta,
10019 StaParams.htcap_present);
10020
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010022 &StaParams,
10023 isBufSta,
10024 isOffChannelSupported,
10025 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010026 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010027 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010028 return -EINVAL;
10029 }
10030
10031 status =
10032 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10033 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010034 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010035 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010036 return -EINVAL;
10037 }
10038 }
10039#endif
10040 }
10041 EXIT();
10042 return ret;
10043}
10044
10045/**
10046 * wlan_hdd_change_station() - cfg80211 change station handler function
10047 * @wiphy: Pointer to the wiphy structure
10048 * @dev: Pointer to the net device.
10049 * @mac: bssid
10050 * @params: Pointer to station parameters
10051 *
10052 * This is the cfg80211 change station handler function which invokes
10053 * the internal function @__wlan_hdd_change_station with
10054 * SSR protection.
10055 *
10056 * Return: 0 for success, error number on failure.
10057 */
10058#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10059static int wlan_hdd_change_station(struct wiphy *wiphy,
10060 struct net_device *dev,
10061 const u8 *mac,
10062 struct station_parameters *params)
10063#else
10064static int wlan_hdd_change_station(struct wiphy *wiphy,
10065 struct net_device *dev,
10066 u8 *mac,
10067 struct station_parameters *params)
10068#endif
10069{
10070 int ret;
10071
10072 cds_ssr_protect(__func__);
10073 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10074 cds_ssr_unprotect(__func__);
10075
10076 return ret;
10077}
10078
10079/*
10080 * FUNCTION: __wlan_hdd_cfg80211_add_key
10081 * This function is used to initialize the key information
10082 */
10083static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10084 struct net_device *ndev,
10085 u8 key_index, bool pairwise,
10086 const u8 *mac_addr,
10087 struct key_params *params)
10088{
10089 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10090 tCsrRoamSetKey setKey;
10091 int status;
10092 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010094 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010095 hdd_context_t *pHddCtx;
10096 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10097
10098 ENTER();
10099
Anurag Chouhan6d760662016-02-20 16:05:43 +053010100 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010101 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102 return -EINVAL;
10103 }
10104
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010105 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10106 hdd_err("invalid session id: %d", pAdapter->sessionId);
10107 return -EINVAL;
10108 }
10109
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010110 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10112 pAdapter->sessionId, params->key_len));
10113 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10114 status = wlan_hdd_validate_context(pHddCtx);
10115
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010116 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010119 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010120 hdd_device_mode_to_string(pAdapter->device_mode),
10121 pAdapter->device_mode);
10122
10123 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010124 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010125
10126 return -EINVAL;
10127 }
10128
10129 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010130 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131
10132 return -EINVAL;
10133 }
10134
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010135 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136
10137 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010138 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010139 setKey.keyId = key_index;
10140 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010141 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010142
10143 switch (params->cipher) {
10144 case WLAN_CIPHER_SUITE_WEP40:
10145 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10146 break;
10147
10148 case WLAN_CIPHER_SUITE_WEP104:
10149 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10150 break;
10151
10152 case WLAN_CIPHER_SUITE_TKIP:
10153 {
10154 u8 *pKey = &setKey.Key[0];
10155 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10156
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010157 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158
10159 /*Supplicant sends the 32bytes key in this order
10160
10161 |--------------|----------|----------|
10162 | Tk1 |TX-MIC | RX Mic |
10163 |||--------------|----------|----------|
10164 <---16bytes---><--8bytes--><--8bytes-->
10165
10166 */
10167 /*Sme expects the 32 bytes key to be in the below order
10168
10169 |--------------|----------|----------|
10170 | Tk1 |RX-MIC | TX Mic |
10171 |||--------------|----------|----------|
10172 <---16bytes---><--8bytes--><--8bytes-->
10173 */
10174 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010175 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176
10177 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010178 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179
10180 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010181 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010182
10183 break;
10184 }
10185
10186 case WLAN_CIPHER_SUITE_CCMP:
10187 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10188 break;
10189
10190#ifdef FEATURE_WLAN_WAPI
10191 case WLAN_CIPHER_SUITE_SMS4:
10192 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010193 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010194 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10195 mac_addr, params->key,
10196 params->key_len);
10197 return 0;
10198 }
10199#endif
10200
10201#ifdef FEATURE_WLAN_ESE
10202 case WLAN_CIPHER_SUITE_KRK:
10203 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10204 break;
10205#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10206 case WLAN_CIPHER_SUITE_BTK:
10207 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10208 break;
10209#endif
10210#endif
10211
10212#ifdef WLAN_FEATURE_11W
10213 case WLAN_CIPHER_SUITE_AES_CMAC:
10214 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10215 break;
10216#endif
10217
10218 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010219 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010220 return -EOPNOTSUPP;
10221 }
10222
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010223 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224
10225 if (!pairwise) {
10226 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010227 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010229 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010230 } else {
10231 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010232 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010233 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010234 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010235 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010236 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010237 /* if a key is already installed, block all subsequent ones */
10238 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010239 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010240 return 0;
10241 }
10242
10243 setKey.keyDirection = eSIR_TX_RX;
10244 /*Set the group key */
10245 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10246 pAdapter->sessionId, &setKey, &roamId);
10247
10248 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010249 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250 return -EINVAL;
10251 }
10252 /*Save the keys here and call sme_roam_set_key for setting
10253 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010254 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255 &setKey, sizeof(tCsrRoamSetKey));
10256
10257 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10258 return status;
10259 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010260 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10261 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10263 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010264 status = wlansap_set_key_sta(
10265 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010266 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010267 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268 __LINE__, status);
10269 }
10270 }
10271
10272 /* Save the key in ap ctx for use on START_BASS and restart */
10273 if (pairwise ||
10274 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10275 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010276 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010277 sizeof(tCsrRoamSetKey));
10278 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010279 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010280 sizeof(tCsrRoamSetKey));
10281
Krunal Sonib4326f22016-03-10 13:05:51 -080010282 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10283 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284 hdd_wext_state_t *pWextState =
10285 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10286 hdd_station_ctx_t *pHddStaCtx =
10287 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10288
10289 if (!pairwise) {
10290 /* set group key */
10291 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010292 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 __func__, __LINE__);
10294 hdd_perform_roam_set_key_complete(pAdapter);
10295 }
10296 }
10297
10298 pWextState->roamProfile.Keys.KeyLength[key_index] =
10299 (u8) params->key_len;
10300
10301 pWextState->roamProfile.Keys.defaultIndex = key_index;
10302
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010303 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304 KeyMaterial[key_index][0], params->key,
10305 params->key_len);
10306
10307 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10308
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010309 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010310 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10311 setKey.keyDirection);
10312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010313 /* The supplicant may attempt to set the PTK once pre-authentication
10314 is done. Save the key in the UMAC and include it in the ADD BSS
10315 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010316 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010317 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010318 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010319 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010320 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010321 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010322 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 return -EINVAL;
10324 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010325
10326 /* issue set key request to SME */
10327 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10328 pAdapter->sessionId, &setKey, &roamId);
10329
10330 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010331 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010332 pHddStaCtx->roam_info.roamingState =
10333 HDD_ROAM_STATE_NONE;
10334 return -EINVAL;
10335 }
10336
10337 /* in case of IBSS as there was no information available about WEP keys during
10338 * IBSS join, group key intialized with NULL key, so re-initialize group key
10339 * with correct value*/
10340 if ((eCSR_BSS_TYPE_START_IBSS ==
10341 pWextState->roamProfile.BSSType)
10342 &&
10343 !((IW_AUTH_KEY_MGMT_802_1X ==
10344 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10345 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10346 pHddStaCtx->conn_info.authType)
10347 )
10348 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10349 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10350 )
10351 ) {
10352 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010353 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010355 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10357 setKey.keyDirection);
10358
10359 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10360 pAdapter->sessionId, &setKey,
10361 &roamId);
10362
10363 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010364 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010365 pHddStaCtx->roam_info.roamingState =
10366 HDD_ROAM_STATE_NONE;
10367 return -EINVAL;
10368 }
10369 }
10370 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010371 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010372 return 0;
10373}
10374
10375static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10376 struct net_device *ndev,
10377 u8 key_index, bool pairwise,
10378 const u8 *mac_addr,
10379 struct key_params *params)
10380{
10381 int ret;
10382 cds_ssr_protect(__func__);
10383 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10384 mac_addr, params);
10385 cds_ssr_unprotect(__func__);
10386
10387 return ret;
10388}
10389
10390/*
10391 * FUNCTION: __wlan_hdd_cfg80211_get_key
10392 * This function is used to get the key information
10393 */
10394static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10395 struct net_device *ndev,
10396 u8 key_index, bool pairwise,
10397 const u8 *mac_addr, void *cookie,
10398 void (*callback)(void *cookie,
10399 struct key_params *)
10400 )
10401{
10402 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10403 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10404 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10405 struct key_params params;
10406
10407 ENTER();
10408
Anurag Chouhan6d760662016-02-20 16:05:43 +053010409 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010410 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 return -EINVAL;
10412 }
10413
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010414 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415 hdd_device_mode_to_string(pAdapter->device_mode),
10416 pAdapter->device_mode);
10417
10418 memset(&params, 0, sizeof(params));
10419
10420 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010421 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 key_index);
10423 return -EINVAL;
10424 }
10425
10426 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10427 case eCSR_ENCRYPT_TYPE_NONE:
10428 params.cipher = IW_AUTH_CIPHER_NONE;
10429 break;
10430
10431 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10432 case eCSR_ENCRYPT_TYPE_WEP40:
10433 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10434 break;
10435
10436 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10437 case eCSR_ENCRYPT_TYPE_WEP104:
10438 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10439 break;
10440
10441 case eCSR_ENCRYPT_TYPE_TKIP:
10442 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10443 break;
10444
10445 case eCSR_ENCRYPT_TYPE_AES:
10446 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10447 break;
10448
10449 default:
10450 params.cipher = IW_AUTH_CIPHER_NONE;
10451 break;
10452 }
10453
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010454 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010455 TRACE_CODE_HDD_CFG80211_GET_KEY,
10456 pAdapter->sessionId, params.cipher));
10457
10458 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10459 params.seq_len = 0;
10460 params.seq = NULL;
10461 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10462 callback(cookie, &params);
10463
10464 EXIT();
10465 return 0;
10466}
10467
10468static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10469 struct net_device *ndev,
10470 u8 key_index, bool pairwise,
10471 const u8 *mac_addr, void *cookie,
10472 void (*callback)(void *cookie,
10473 struct key_params *)
10474 )
10475{
10476 int ret;
10477
10478 cds_ssr_protect(__func__);
10479 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10480 mac_addr, cookie, callback);
10481 cds_ssr_unprotect(__func__);
10482
10483 return ret;
10484}
10485
10486/**
10487 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10488 * @wiphy: wiphy interface context
10489 * @ndev: pointer to net device
10490 * @key_index: Key index used in 802.11 frames
10491 * @unicast: true if it is unicast key
10492 * @multicast: true if it is multicast key
10493 *
10494 * This function is required for cfg80211_ops API.
10495 * It is used to delete the key information
10496 * Underlying hardware implementation does not have API to delete the
10497 * encryption key. It is automatically deleted when the peer is
10498 * removed. Hence this function currently does nothing.
10499 * Future implementation may interprete delete key operation to
10500 * replacing the key with a random junk value, effectively making it
10501 * useless.
10502 *
10503 * Return: status code, always 0.
10504 */
10505
10506static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10507 struct net_device *ndev,
10508 u8 key_index,
10509 bool pairwise, const u8 *mac_addr)
10510{
10511 EXIT();
10512 return 0;
10513}
10514
10515/**
10516 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10517 * @wiphy: Pointer to wiphy structure.
10518 * @dev: Pointer to net_device structure.
10519 * @key_index: key index
10520 * @pairwise: pairwise
10521 * @mac_addr: mac address
10522 *
10523 * This is the cfg80211 delete key handler function which invokes
10524 * the internal function @__wlan_hdd_cfg80211_del_key with
10525 * SSR protection.
10526 *
10527 * Return: 0 for success, error number on failure.
10528 */
10529static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10530 struct net_device *dev,
10531 u8 key_index,
10532 bool pairwise, const u8 *mac_addr)
10533{
10534 int ret;
10535
10536 cds_ssr_protect(__func__);
10537 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10538 pairwise, mac_addr);
10539 cds_ssr_unprotect(__func__);
10540
10541 return ret;
10542}
10543
10544/*
10545 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10546 * This function is used to set the default tx key index
10547 */
10548static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10549 struct net_device *ndev,
10550 u8 key_index,
10551 bool unicast, bool multicast)
10552{
10553 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10554 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10555 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10556 hdd_context_t *pHddCtx;
10557 int status;
10558
10559 ENTER();
10560
Anurag Chouhan6d760662016-02-20 16:05:43 +053010561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010562 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010563 return -EINVAL;
10564 }
10565
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010566 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10567 hdd_err("invalid session id: %d", pAdapter->sessionId);
10568 return -EINVAL;
10569 }
10570
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010571 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010572 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10573 pAdapter->sessionId, key_index));
10574
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010575 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010576 hdd_device_mode_to_string(pAdapter->device_mode),
10577 pAdapter->device_mode, key_index);
10578
10579 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010580 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010581 return -EINVAL;
10582 }
10583
10584 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10585 status = wlan_hdd_validate_context(pHddCtx);
10586
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010587 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010588 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010589
Krunal Sonib4326f22016-03-10 13:05:51 -080010590 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10591 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010592 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10593 pHddStaCtx->conn_info.ucEncryptionType) &&
10594 (eCSR_ENCRYPT_TYPE_AES !=
10595 pHddStaCtx->conn_info.ucEncryptionType)) {
10596 /* If default key index is not same as previous one,
10597 * then update the default key index */
10598
10599 tCsrRoamSetKey setKey;
10600 uint32_t roamId = 0xFF;
10601 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10602
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010603 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010604
10605 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010606 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 setKey.keyId = key_index;
10608 setKey.keyLength = Keys->KeyLength[key_index];
10609
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010610 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010611 &Keys->KeyMaterial[key_index][0],
10612 Keys->KeyLength[key_index]);
10613
10614 setKey.keyDirection = eSIR_TX_RX;
10615
Anurag Chouhanc5548422016-02-24 18:33:27 +053010616 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010617 &pHddStaCtx->conn_info.bssId);
10618
10619 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10620 pWextState->roamProfile.EncryptionType.
10621 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10622 /* In the case of dynamic wep supplicant hardcodes DWEP type
10623 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10624 * WEP-40 encryption. In this canse the key length is 5 but the
10625 * encryption type is 104 hence checking the key langht(5) and
10626 * encryption type(104) and switching encryption type to 40*/
10627 pWextState->roamProfile.EncryptionType.
10628 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10629 pWextState->roamProfile.mcEncryptionType.
10630 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10631 }
10632
10633 setKey.encType =
10634 pWextState->roamProfile.EncryptionType.
10635 encryptionType[0];
10636
10637 /* Issue set key request */
10638 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10639 pAdapter->sessionId, &setKey,
10640 &roamId);
10641
10642 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010643 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 status);
10645 return -EINVAL;
10646 }
10647 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010648 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 /* In SoftAp mode setting key direction for default mode */
10650 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10651 pWextState->roamProfile.EncryptionType.encryptionType[0])
10652 && (eCSR_ENCRYPT_TYPE_AES !=
10653 pWextState->roamProfile.EncryptionType.
10654 encryptionType[0])) {
10655 /* Saving key direction for default key index to TX default */
10656 hdd_ap_ctx_t *pAPCtx =
10657 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10658 pAPCtx->wepKey[key_index].keyDirection =
10659 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010660 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010661 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010662 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663 }
10664 }
10665
10666 EXIT();
10667 return status;
10668}
10669
10670static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10671 struct net_device *ndev,
10672 u8 key_index,
10673 bool unicast, bool multicast)
10674{
10675 int ret;
10676 cds_ssr_protect(__func__);
10677 ret =
10678 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10679 multicast);
10680 cds_ssr_unprotect(__func__);
10681
10682 return ret;
10683}
10684
Abhishek Singhc9941602016-08-09 16:06:22 +053010685/*
10686 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10687 * @wiphy: wiphy pointer
10688 * @channel: channel of the BSS
10689 * @bssid: Bssid of BSS
10690 * @ssid: Ssid of the BSS
10691 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010692 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010693 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010695#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010696static
Abhishek Singhc9941602016-08-09 16:06:22 +053010697struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10698 struct ieee80211_channel *channel, const u8 *bssid,
10699 const u8 *ssid, size_t ssid_len)
10700{
10701 return cfg80211_get_bss(wiphy, channel, bssid,
10702 ssid,
10703 ssid_len,
10704 WLAN_CAPABILITY_ESS,
10705 WLAN_CAPABILITY_ESS);
10706}
10707#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010708static
Abhishek Singhc9941602016-08-09 16:06:22 +053010709struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10710 struct ieee80211_channel *channel, const u8 *bssid,
10711 const u8 *ssid, size_t ssid_len)
10712{
10713 return cfg80211_get_bss(wiphy, channel, bssid,
10714 ssid,
10715 ssid_len,
10716 IEEE80211_BSS_TYPE_ESS,
10717 IEEE80211_PRIVACY_ANY);
10718}
10719#endif
10720
10721
10722/*
10723 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10724 * interface that BSS might have been lost.
10725 * @pAdapter: adaptor
10726 * @bssid: bssid which might have been lost
10727 *
10728 * Return: bss which is unlinked from kernel cache
10729 */
10730struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10731 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010732{
10733 struct net_device *dev = pAdapter->dev;
10734 struct wireless_dev *wdev = dev->ieee80211_ptr;
10735 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010736 struct cfg80211_bss *bss = NULL;
10737
Abhishek Singhc9941602016-08-09 16:06:22 +053010738 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10739 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010740 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010741 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010742 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010743 hdd_info("cfg80211_unlink_bss called for BSSID "
10744 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010745 cfg80211_unlink_bss(wiphy, bss);
10746 }
10747 return bss;
10748}
10749
Abhishek Singhc9941602016-08-09 16:06:22 +053010750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751/**
10752 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10753 * @pAdapter: Pointer to adapter
10754 * @bss_desc: Pointer to bss descriptor
10755 *
10756 * This function is used to inform the BSS details to nl80211 interface.
10757 *
10758 * Return: struct cfg80211_bss pointer
10759 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010760struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10761 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762{
10763 /*
10764 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10765 * already exists in bss data base of cfg80211 for that particular BSS
10766 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10767 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10768 * As of now there is no possibility to get the mgmt(probe response)
10769 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10770 * and passing to cfg80211_inform_bss_frame.
10771 */
10772 struct net_device *dev = pAdapter->dev;
10773 struct wireless_dev *wdev = dev->ieee80211_ptr;
10774 struct wiphy *wiphy = wdev->wiphy;
10775 int chan_no = bss_desc->channelId;
10776#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10777 qcom_ie_age *qie_age = NULL;
10778 int ie_length =
10779 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10780#else
10781 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10782#endif
10783 const char *ie =
10784 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10785 unsigned int freq;
10786 struct ieee80211_channel *chan;
10787 struct ieee80211_mgmt *mgmt = NULL;
10788 struct cfg80211_bss *bss_status = NULL;
10789 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10790 int rssi = 0;
10791 hdd_context_t *pHddCtx;
10792 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010794 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010795
10796 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10797 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010798 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010800
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010801 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10803 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010804 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010805 return NULL;
10806 }
10807
10808 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10809
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810 /* Android does not want the timestamp from the frame.
10811 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010812 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813 mgmt->u.probe_resp.timestamp =
10814 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010815
10816 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10817 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10818
10819#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10820 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10821 /* Assuming this is the last IE, copy at the end */
10822 ie_length -= sizeof(qcom_ie_age);
10823 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10824 qie_age->element_id = QCOM_VENDOR_IE_ID;
10825 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10826 qie_age->oui_1 = QCOM_OUI1;
10827 qie_age->oui_2 = QCOM_OUI2;
10828 qie_age->oui_3 = QCOM_OUI3;
10829 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053010830 /*
10831 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10832 * all bss related timestamp is in units of ms. Due to this when scan
10833 * results are sent to lowi the scan age is high.To address this,
10834 * send age in units of 1/10 ms.
10835 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010836 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053010837 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010838 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010839 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10840 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010841 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10842 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843#endif
10844
10845 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10846 if (bss_desc->fProbeRsp) {
10847 mgmt->frame_control |=
10848 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10849 } else {
10850 mgmt->frame_control |=
10851 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10852 }
10853
10854 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010855 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 freq =
10857 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010858 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010860 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 freq =
10862 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010863 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010865 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 kfree(mgmt);
10867 return NULL;
10868 }
10869
10870 chan = __ieee80211_get_channel(wiphy, freq);
10871 /* When the band is changed on the fly using the GUI, three things are done
10872 * 1. scan abort
10873 * 2. flush scan results from cache
10874 * 3. update the band with the new band user specified (refer to the
10875 * hdd_set_band_helper function) as part of the scan abort, message will be
10876 * queued to PE and we proceed with flushing and changinh the band.
10877 * PE will stop the scanning further and report back the results what ever
10878 * it had till now by calling the call back function.
10879 * if the time between update band and scandone call back is sufficient
10880 * enough the band change reflects in SME, SME validates the channels
10881 * and discards the channels correponding to previous band and calls back
10882 * with zero bss results. but if the time between band update and scan done
10883 * callback is very small then band change will not reflect in SME and SME
10884 * reports to HDD all the channels correponding to previous band.this is due
10885 * to race condition.but those channels are invalid to the new band and so
10886 * this function __ieee80211_get_channel will return NULL.Each time we
10887 * report scan result with this pointer null warning kernel trace is printed.
10888 * if the scan results contain large number of APs continuosly kernel
10889 * warning trace is printed and it will lead to apps watch dog bark.
10890 * So drop the bss and continue to next bss.
10891 */
10892 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010893 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10894 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 kfree(mgmt);
10896 return NULL;
10897 }
10898
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010899 /* Based on .ini configuration, raw rssi can be reported for bss.
10900 * Raw rssi is typically used for estimating power.
10901 */
10902
10903 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10904 bss_desc->rssi;
10905
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010906 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010907 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010908
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053010909 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010911 (int)(rssi / 100),
10912 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913
10914 bss_status =
10915 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10916 GFP_KERNEL);
10917 kfree(mgmt);
10918 return bss_status;
10919}
10920
10921/**
10922 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10923 * @pAdapter: Pointer to adapter
10924 * @pRoamInfo: Pointer to roam info
10925 *
10926 * This function is used to update the BSS data base of CFG8011
10927 *
10928 * Return: struct cfg80211_bss pointer
10929 */
10930struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10931 tCsrRoamInfo *pRoamInfo)
10932{
10933 tCsrRoamConnectedProfile roamProfile;
10934 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10935 struct cfg80211_bss *bss = NULL;
10936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010937 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10938 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10939
10940 if (NULL != roamProfile.pBssDesc) {
10941 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10942 roamProfile.pBssDesc);
10943
10944 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010945 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010946
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010947 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010949 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951 return bss;
10952}
10953/**
10954 * wlan_hdd_cfg80211_update_bss() - update bss
10955 * @wiphy: Pointer to wiphy
10956 * @pAdapter: Pointer to adapter
10957 * @scan_time: scan request timestamp
10958 *
10959 * Return: zero if success, non-zero otherwise
10960 */
10961int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10962 hdd_adapter_t *pAdapter,
10963 uint32_t scan_time)
10964{
10965 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10966 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010967 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010968 tScanResultHandle pResult;
10969 struct cfg80211_bss *bss_status = NULL;
10970 hdd_context_t *pHddCtx;
10971 int ret;
10972
10973 ENTER();
10974
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010975 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10976 hdd_err("invalid session id: %d", pAdapter->sessionId);
10977 return -EINVAL;
10978 }
10979
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010980 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010981 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10982 NO_SESSION, pAdapter->sessionId));
10983
10984 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10985 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010986 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010988
10989 /* start getting scan results and populate cgf80211 BSS database */
10990 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10991
10992 /* no scan results */
10993 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010994 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010995 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996 }
10997
10998 pScanResult = sme_scan_result_get_first(hHal, pResult);
10999
11000 while (pScanResult) {
11001 /*
11002 * - cfg80211_inform_bss() is not updating ie field of bss
11003 * entry if entry already exists in bss data base of cfg80211
11004 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11005 * to update thebss entry instead of cfg80211_inform_bss,
11006 * But this call expects mgmt packet as input. As of now
11007 * there is no possibility to get the mgmt(probe response)
11008 * frame from PE, converting bss_desc to
11009 * ieee80211_mgmt(probe response) and passing to c
11010 * fg80211_inform_bss_frame.
11011 * - Update BSS only if beacon timestamp is later than
11012 * scan request timestamp.
11013 */
11014 if ((scan_time == 0) ||
11015 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011016 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011017 bss_status =
11018 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11019 &pScanResult->BssDescriptor);
11020
11021 if (NULL == bss_status) {
11022 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11023 } else {
11024 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 bss_status);
11027 }
11028 } else {
11029 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11030 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11031 }
11032 pScanResult = sme_scan_result_get_next(hHal, pResult);
11033 }
11034
11035 sme_scan_result_purge(hHal, pResult);
11036 /*
11037 * For SAP mode, scan is invoked by hostapd during SAP start
11038 * if hostapd is restarted, we need to flush previous scan
11039 * result so that it will reflect environment change
11040 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011041 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011042#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11043 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11044#endif
11045 )
11046 sme_scan_flush_result(hHal);
11047
11048 EXIT();
11049 return 0;
11050}
11051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052/**
11053 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11054 * @pAdapter: Pointer to adapter
11055 * @pRoamInfo: Pointer to roam info
11056 * @index: Index
11057 * @preauth: Preauth flag
11058 *
11059 * This function is used to notify the supplicant of a new PMKSA candidate.
11060 *
11061 * Return: 0 for success, non-zero for failure
11062 */
11063int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11064 tCsrRoamInfo *pRoamInfo,
11065 int index, bool preauth)
11066{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067 struct net_device *dev = pAdapter->dev;
11068 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11069
11070 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011071 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011072
11073 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011074 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011075 return -EINVAL;
11076 }
11077
11078 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011079 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11081 cfg80211_pmksa_candidate_notify(dev, index,
11082 pRoamInfo->bssid.bytes,
11083 preauth, GFP_KERNEL);
11084 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011085 return 0;
11086}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087
11088#ifdef FEATURE_WLAN_LFR_METRICS
11089/**
11090 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11091 * @pAdapter: Pointer to adapter
11092 * @pRoamInfo: Pointer to roam info
11093 *
11094 * 802.11r/LFR metrics reporting function to report preauth initiation
11095 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011096 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011097 */
11098#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011099QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011100 tCsrRoamInfo *pRoamInfo)
11101{
11102 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11103 union iwreq_data wrqu;
11104
11105 ENTER();
11106
11107 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011108 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011109 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 }
11111
11112 /* create the event */
11113 memset(&wrqu, 0, sizeof(wrqu));
11114 memset(metrics_notification, 0, sizeof(metrics_notification));
11115
11116 wrqu.data.pointer = metrics_notification;
11117 wrqu.data.length = scnprintf(metrics_notification,
11118 sizeof(metrics_notification),
11119 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11120 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11121
11122 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11123 metrics_notification);
11124
11125 EXIT();
11126
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011127 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128}
11129
11130/**
11131 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11132 * @pAdapter: Pointer to adapter
11133 * @pRoamInfo: Pointer to roam info
11134 * @preauth_status: Preauth status
11135 *
11136 * 802.11r/LFR metrics reporting function to report handover initiation
11137 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011138 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011140QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11142 tCsrRoamInfo *pRoamInfo,
11143 bool preauth_status)
11144{
11145 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11146 union iwreq_data wrqu;
11147
11148 ENTER();
11149
11150 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011151 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011152 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 }
11154
11155 /* create the event */
11156 memset(&wrqu, 0, sizeof(wrqu));
11157 memset(metrics_notification, 0, sizeof(metrics_notification));
11158
11159 scnprintf(metrics_notification, sizeof(metrics_notification),
11160 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11161 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11162
11163 if (1 == preauth_status)
11164 strlcat(metrics_notification, " true",
11165 sizeof(metrics_notification));
11166 else
11167 strlcat(metrics_notification, " false",
11168 sizeof(metrics_notification));
11169
11170 wrqu.data.pointer = metrics_notification;
11171 wrqu.data.length = strlen(metrics_notification);
11172
11173 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11174 metrics_notification);
11175
11176 EXIT();
11177
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011178 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011179}
11180
11181/**
11182 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11183 * @pAdapter: Pointer to adapter
11184 * @pRoamInfo: Pointer to roam info
11185 *
11186 * 802.11r/LFR metrics reporting function to report handover initiation
11187 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011188 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011189 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011190QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011191 tCsrRoamInfo *pRoamInfo)
11192{
11193 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11194 union iwreq_data wrqu;
11195
11196 ENTER();
11197
11198 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011199 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011200 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201 }
11202
11203 /* create the event */
11204 memset(&wrqu, 0, sizeof(wrqu));
11205 memset(metrics_notification, 0, sizeof(metrics_notification));
11206
11207 wrqu.data.pointer = metrics_notification;
11208 wrqu.data.length = scnprintf(metrics_notification,
11209 sizeof(metrics_notification),
11210 "QCOM: LFR_PREAUTH_HANDOVER "
11211 MAC_ADDRESS_STR,
11212 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11213
11214 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11215 metrics_notification);
11216
11217 EXIT();
11218
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011219 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220}
11221#endif
11222
11223/**
11224 * hdd_select_cbmode() - select channel bonding mode
11225 * @pAdapter: Pointer to adapter
11226 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011227 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011228 *
11229 * Return: none
11230 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011231void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11232 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011234 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011235 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011236 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011237
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011238 /*
11239 * CDS api expects secondary channel for calculating
11240 * the channel params
11241 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011242 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011243 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11244 if (operationChannel >= 1 && operationChannel <= 5)
11245 sec_ch = operationChannel + 4;
11246 else if (operationChannel >= 6 && operationChannel <= 13)
11247 sec_ch = operationChannel - 4;
11248 }
11249
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011251 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011252
11253 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011254 eHddDot11Mode hdd_dot11_mode;
11255 uint8_t iniDot11Mode =
11256 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11257
11258 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11259 switch (iniDot11Mode) {
11260 case eHDD_DOT11_MODE_AUTO:
11261 case eHDD_DOT11_MODE_11ac:
11262 case eHDD_DOT11_MODE_11ac_ONLY:
11263 if (sme_is_feature_supported_by_fw(DOT11AC))
11264 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11265 else
11266 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11267 break;
11268 case eHDD_DOT11_MODE_11n:
11269 case eHDD_DOT11_MODE_11n_ONLY:
11270 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11271 break;
11272 default:
11273 hdd_dot11_mode = iniDot11Mode;
11274 break;
11275 }
11276 ch_info->channel_width = ch_params->ch_width;
11277 ch_info->phy_mode =
11278 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011279 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011280 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011281 hdd_info("ch_info width %d, phymode %d channel %d",
11282 ch_info->channel_width, ch_info->phy_mode,
11283 ch_info->channel);
11284 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285}
11286
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011287/**
11288 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11289 * @adapter: STA adapter
11290 * @roam_profile: STA roam profile
11291 *
11292 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11293 *
11294 * Return: false if sta-sap conc is not allowed, else return true
11295 */
11296static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11297 tCsrRoamProfile *roam_profile)
11298{
11299 hdd_context_t *hdd_ctx;
11300 hdd_adapter_t *ap_adapter;
11301 hdd_ap_ctx_t *hdd_ap_ctx;
11302 hdd_hostapd_state_t *hostapd_state;
11303 uint8_t channel = 0;
11304 QDF_STATUS status;
11305
11306 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11307 if (!hdd_ctx) {
11308 hdd_err("HDD context is NULL");
11309 return true;
11310 }
11311
11312 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11313 /* probably no sap running, no handling required */
11314 if (ap_adapter == NULL)
11315 return true;
11316
11317 /*
11318 * sap is not in started state, so it is fine to go ahead with sta.
11319 * if sap is currently doing CAC then don't allow sta to go further.
11320 */
11321 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11322 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11323 return true;
11324
11325 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11326 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11327 return false;
11328 }
11329
11330 /*
11331 * log and return error, if we allow STA to go through, we don't
11332 * know what is going to happen better stop sta connection
11333 */
11334 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11335 if (NULL == hdd_ap_ctx) {
11336 hdd_err("AP context not found");
11337 return false;
11338 }
11339
11340 /* sap is on non-dfs channel, nothing to handle */
11341 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11342 hdd_info("sap is on non-dfs channel, sta is allowed");
11343 return true;
11344 }
11345 /*
11346 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011347 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011348 */
11349 status = cds_get_channel_from_scan_result(adapter,
11350 roam_profile, &channel);
11351
Nitesh Shah59774522016-09-16 15:14:21 +053011352 /*
11353 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11354 * channels for roaming case.
11355 */
11356 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11357 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11358 return true;
11359 }
11360
11361 /*
11362 * If channel is 0 or DFS then better to call pcl and find out the
11363 * best channel. If channel is non-dfs 5 GHz then better move SAP
11364 * to STA's channel to make scc, so we have room for 3port MCC
11365 * scenario.
11366 */
11367 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011368 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11369 true);
11370
11371 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11372 qdf_event_reset(&hostapd_state->qdf_event);
11373 status = wlansap_set_channel_change_with_csa(
11374 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11375 hdd_ap_ctx->sapConfig.ch_width_orig);
11376
11377 if (QDF_STATUS_SUCCESS != status) {
11378 hdd_err("Set channel with CSA IE failed, can't allow STA");
11379 return false;
11380 }
11381
11382 /*
11383 * wait here for SAP to finish the channel switch. When channel
11384 * switch happens, SAP sends few beacons with CSA_IE. After
11385 * successfully Transmission of those beacons, it will move its
11386 * state from started to disconnected and move to new channel.
11387 * once it moves to new channel, sap again moves its state
11388 * machine from disconnected to started and set this event.
11389 * wait for 10 secs to finish this.
11390 */
11391 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11392 if (!QDF_IS_STATUS_SUCCESS(status)) {
11393 hdd_err("wait for qdf_event failed, STA not allowed!!");
11394 return false;
11395 }
11396
11397 return true;
11398}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399
Krunal Soni31949422016-07-29 17:17:53 -070011400/**
11401 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011403 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011404 * @ssid_len: Length of ssid
11405 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011406 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011407 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011408 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 *
11410 * This function is used to start the association process
11411 *
11412 * Return: 0 for success, non-zero for failure
11413 */
Krunal Soni31949422016-07-29 17:17:53 -070011414static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011415 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011416 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011417 u8 operatingChannel,
11418 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419{
11420 int status = 0;
11421 hdd_wext_state_t *pWextState;
11422 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011423 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011424 uint32_t roamId;
11425 tCsrRoamProfile *pRoamProfile;
11426 eCsrAuthType RSNAuthType;
11427 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011428 uint8_t channel = 0;
11429 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430
11431 ENTER();
11432
11433 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11434 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011435 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011436
11437 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011438 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011439 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440
11441 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011442 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011443 return -EINVAL;
11444 }
11445
11446 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011447 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11448 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011449
11450 if (pRoamProfile) {
11451 hdd_station_ctx_t *pHddStaCtx;
11452 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11453
11454 if (HDD_WMM_USER_MODE_NO_QOS ==
11455 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11456 /*QoS not enabled in cfg file */
11457 pRoamProfile->uapsd_mask = 0;
11458 } else {
11459 /*QoS enabled, update uapsd mask from cfg file */
11460 pRoamProfile->uapsd_mask =
11461 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11462 }
11463
11464 pRoamProfile->SSIDs.numOfSSIDs = 1;
11465 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011466 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011468 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011469 ssid, ssid_len);
11470
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011471 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 if (bssid) {
11473 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011474 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011475 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011476 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011477 /*
11478 * Save BSSID in seperate variable as
11479 * pRoamProfile's BSSID is getting zeroed out in the
11480 * association process. In case of join failure
11481 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011482 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011483 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011484 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011485 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011486 } else if (bssid_hint) {
11487 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011488 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011489 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011490 /*
11491 * Save BSSID in a separate variable as
11492 * pRoamProfile's BSSID is getting zeroed out in the
11493 * association process. In case of join failure
11494 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011496 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011497 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011498 hdd_info("bssid_hint is given by upper layer %pM",
11499 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011501 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011502 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011503 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 }
11505
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011506 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507 pRoamProfile->SSIDs.SSIDList->SSID.length,
11508 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11509 operatingChannel);
11510
11511 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11512 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11515 }
11516#ifdef FEATURE_WLAN_WAPI
11517 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011518 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519 switch (pAdapter->wapi_info.wapiAuthMode) {
11520 case WAPI_AUTH_MODE_PSK:
11521 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011522 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 pAdapter->wapi_info.wapiAuthMode);
11524 pRoamProfile->AuthType.authType[0] =
11525 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11526 break;
11527 }
11528 case WAPI_AUTH_MODE_CERT:
11529 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011530 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011531 pAdapter->wapi_info.wapiAuthMode);
11532 pRoamProfile->AuthType.authType[0] =
11533 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11534 break;
11535 }
11536 } /* End of switch */
11537 if (pAdapter->wapi_info.wapiAuthMode ==
11538 WAPI_AUTH_MODE_PSK
11539 || pAdapter->wapi_info.wapiAuthMode ==
11540 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011541 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011542 pRoamProfile->AuthType.numEntries = 1;
11543 pRoamProfile->EncryptionType.numEntries = 1;
11544 pRoamProfile->EncryptionType.encryptionType[0] =
11545 eCSR_ENCRYPT_TYPE_WPI;
11546 pRoamProfile->mcEncryptionType.numEntries = 1;
11547 pRoamProfile->mcEncryptionType.
11548 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11549 }
11550 }
Krunal Soni31949422016-07-29 17:17:53 -070011551#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552#ifdef WLAN_FEATURE_GTK_OFFLOAD
11553 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011554 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11555 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11557 sizeof(tSirGtkOffloadParams));
11558 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11559 GTK_OFFLOAD_DISABLE;
11560 }
11561#endif
11562 pRoamProfile->csrPersona = pAdapter->device_mode;
11563
11564 if (operatingChannel) {
11565 pRoamProfile->ChannelInfo.ChannelList =
11566 &operatingChannel;
11567 pRoamProfile->ChannelInfo.numOfChannels = 1;
11568 } else {
11569 pRoamProfile->ChannelInfo.ChannelList = NULL;
11570 pRoamProfile->ChannelInfo.numOfChannels = 0;
11571 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011572 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 && operatingChannel) {
11574 /*
11575 * Need to post the IBSS power save parameters
11576 * to WMA. WMA will configure this parameters
11577 * to firmware if power save is enabled by the
11578 * firmware.
11579 */
11580 status = hdd_set_ibss_power_save_params(pAdapter);
11581
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011582 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011583 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584 return -EINVAL;
11585 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011586 pRoamProfile->ch_params.ch_width =
11587 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011588 /*
11589 * In IBSS mode while operating in 2.4 GHz,
11590 * the device supports only 20 MHz.
11591 */
11592 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11593 pRoamProfile->ch_params.ch_width =
11594 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011595 hdd_select_cbmode(pAdapter, operatingChannel,
11596 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011597 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011598 /*
11599 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11600 * or pmf=2 is an explicit configuration in the supplicant
11601 * configuration, drop the connection request.
11602 */
11603 if (pWextState->roamProfile.MFPEnabled &&
11604 !(pWextState->roamProfile.MFPRequired ||
11605 pWextState->roamProfile.MFPCapable)) {
11606 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11607 pWextState->roamProfile.MFPEnabled,
11608 pWextState->roamProfile.MFPRequired,
11609 pWextState->roamProfile.MFPCapable);
11610 return -EINVAL;
11611 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612
Krunal Soni3091bcc2016-06-23 12:28:21 -070011613 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011614 hdd_err("Connection refused: conn in progress");
11615 return -EINVAL;
11616 }
11617
Krunal Soni31949422016-07-29 17:17:53 -070011618 /*
11619 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011621 * enhancements, the supplicant is not issuing the scan command
11622 * now. So the unicast frames which are sent from the host are
11623 * not having the additional IEs. If it is P2P CLIENT and there
11624 * is no additional IE present in roamProfile, then use the
11625 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011626 */
11627
Krunal Sonib4326f22016-03-10 13:05:51 -080011628 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011629 (!pRoamProfile->pAddIEScan)) {
11630 pRoamProfile->pAddIEScan =
11631 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11632 pRoamProfile->nAddIEScanLength =
11633 pAdapter->scan_info.scanAddIE.length;
11634 }
11635 /*
11636 * When policy manager is enabled from ini file, we shouldn't
11637 * check for other concurrency rules.
11638 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011639 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011640 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011641 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011642 pAdapter, pRoamProfile, &roamId))
11643 return 0;
11644 }
11645
Krunal Soni3091bcc2016-06-23 12:28:21 -070011646 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011647 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11648 pRoamProfile))) {
11649 hdd_err("sap-sta conc will fail, can't allow sta");
11650 hdd_conn_set_connection_state(pAdapter,
11651 eConnectionState_NotConnected);
11652 return -ENOMEM;
11653 }
11654
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011655 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656 if (!sme_config) {
11657 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011658 hdd_conn_set_connection_state(pAdapter,
11659 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011660 return -ENOMEM;
11661 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011662 sme_get_config_param(pHddCtx->hHal, sme_config);
11663 /* These values are not sessionized. So, any change in these SME
11664 * configs on an older or parallel interface will affect the
11665 * cb mode. So, restoring the default INI params before starting
11666 * interfaces such as sta, cli etc.,
11667 */
11668 sme_config->csrConfig.channelBondingMode5GHz =
11669 pHddCtx->config->nChannelBondingMode5GHz;
11670 sme_config->csrConfig.channelBondingMode24GHz =
11671 pHddCtx->config->nChannelBondingMode24GHz;
11672 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011673 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011674 /*
11675 * Change conn_state to connecting before sme_roam_connect(),
11676 * because sme_roam_connect() has a direct path to call
11677 * hdd_sme_roam_callback(), which will change the conn_state
11678 * If direct path, conn_state will be accordingly changed to
11679 * NotConnected or Associated by either
11680 * hdd_association_completion_handler() or
11681 * hdd_dis_connect_handler() in sme_RoamCallback()if
11682 * sme_RomConnect is to be queued,
11683 * Connecting state will remain until it is completed.
11684 *
11685 * If connection state is not changed, connection state will
11686 * remain in eConnectionState_NotConnected state.
11687 * In hdd_association_completion_handler, "hddDisconInProgress"
11688 * is set to true if conn state is
11689 * eConnectionState_NotConnected.
11690 * If "hddDisconInProgress" is set to true then cfg80211 layer
11691 * is not informed of connect result indication which
11692 * is an issue.
11693 */
11694 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011695 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011696 hdd_conn_set_connection_state(pAdapter,
11697 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698
Komal Seelama89be8d2016-09-29 11:09:26 +053011699 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11700 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11702 pAdapter->sessionId, pRoamProfile,
11703 &roamId);
11704
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011705 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011706 (QDF_STA_MODE == pAdapter->device_mode ||
11707 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011708 hdd_err("sme_roam_connect (session %d) failed with "
11709 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011710 pAdapter->sessionId, status);
11711 /* change back to NotAssociated */
11712 hdd_conn_set_connection_state(pAdapter,
11713 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011714 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11715 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011716 }
11717
11718 pRoamProfile->ChannelInfo.ChannelList = NULL;
11719 pRoamProfile->ChannelInfo.numOfChannels = 0;
11720
Nitesh Shah044fd672016-10-13 18:53:25 +053011721 if (!QDF_IS_STATUS_SUCCESS(
11722 wma_get_current_hw_mode(&hw_mode))) {
11723 hdd_err("wma_get_current_hw_mode failed");
11724 return status;
11725 }
11726
11727 if ((QDF_STA_MODE == pAdapter->device_mode)
11728 && hw_mode.dbs_cap) {
11729 cds_get_channel_from_scan_result(pAdapter,
11730 pRoamProfile, &channel);
11731 if (channel)
11732 cds_checkn_update_hw_mode_single_mac_mode
11733 (channel);
11734 }
11735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011737 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011738 return -EINVAL;
11739 }
11740 EXIT();
11741 return status;
11742}
11743
11744/**
11745 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11746 * @pAdapter: Pointer to adapter
11747 * @auth_type: Auth type
11748 *
11749 * This function is used to set the authentication type (OPEN/SHARED).
11750 *
11751 * Return: 0 for success, non-zero for failure
11752 */
11753static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11754 enum nl80211_auth_type auth_type)
11755{
11756 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11757 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011759 /*set authentication type */
11760 switch (auth_type) {
11761 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011762 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011763 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11764 break;
11765
11766 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011768 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11770 break;
11771
11772 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011773 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11775 break;
11776#ifdef FEATURE_WLAN_ESE
11777 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011778 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011779 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11780 break;
11781#endif
11782
11783 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011784 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011785 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11786 return -EINVAL;
11787 }
11788
11789 pWextState->roamProfile.AuthType.authType[0] =
11790 pHddStaCtx->conn_info.authType;
11791 return 0;
11792}
11793
11794/**
11795 * wlan_hdd_set_akm_suite() - set key management type
11796 * @pAdapter: Pointer to adapter
11797 * @key_mgmt: Key management type
11798 *
11799 * This function is used to set the key mgmt type(PSK/8021x).
11800 *
11801 * Return: 0 for success, non-zero for failure
11802 */
11803static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11804{
11805 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11808#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11809 /*set key mgmt type */
11810 switch (key_mgmt) {
11811 case WLAN_AKM_SUITE_PSK:
11812 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011814 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011815 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11816 break;
11817
11818 case WLAN_AKM_SUITE_8021X_SHA256:
11819 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011821 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11823 break;
11824#ifdef FEATURE_WLAN_ESE
11825#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11826#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11827 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011828 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011829 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11830 break;
11831#endif
11832#ifndef WLAN_AKM_SUITE_OSEN
11833#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11834#endif
11835 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011836 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11838 break;
11839
11840 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011841 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842 return -EINVAL;
11843
11844 }
11845 return 0;
11846}
11847
11848/**
11849 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11850 * @pAdapter: Pointer to adapter
11851 * @cipher: Cipher type
11852 * @ucast: Unicast flag
11853 *
11854 * This function is used to set the encryption type
11855 * (NONE/WEP40/WEP104/TKIP/CCMP).
11856 *
11857 * Return: 0 for success, non-zero for failure
11858 */
11859static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11860 u32 cipher, bool ucast)
11861{
11862 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11863 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11864 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011867 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011868 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11869 } else {
11870
11871 /*set encryption method */
11872 switch (cipher) {
11873 case IW_AUTH_CIPHER_NONE:
11874 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11875 break;
11876
11877 case WLAN_CIPHER_SUITE_WEP40:
11878 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11879 break;
11880
11881 case WLAN_CIPHER_SUITE_WEP104:
11882 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11883 break;
11884
11885 case WLAN_CIPHER_SUITE_TKIP:
11886 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11887 break;
11888
11889 case WLAN_CIPHER_SUITE_CCMP:
11890 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11891 break;
11892#ifdef FEATURE_WLAN_WAPI
11893 case WLAN_CIPHER_SUITE_SMS4:
11894 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11895 break;
11896#endif
11897
11898#ifdef FEATURE_WLAN_ESE
11899 case WLAN_CIPHER_SUITE_KRK:
11900 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11901 break;
11902#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11903 case WLAN_CIPHER_SUITE_BTK:
11904 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11905 break;
11906#endif
11907#endif
11908 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011909 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011910 return -EOPNOTSUPP;
11911 }
11912 }
11913
11914 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011915 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011916 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11917 pWextState->roamProfile.EncryptionType.numEntries = 1;
11918 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11919 encryptionType;
11920 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011921 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011922 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11923 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11924 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11925 encryptionType;
11926 }
11927
11928 return 0;
11929}
11930
11931/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011932 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11933 * @wext_state: Pointer to wext state
11934 * @gen_ie: Pointer to IE data
11935 * @len: length of IE data
11936 *
11937 * Return: 0 for success, non-zero for failure
11938 */
11939static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11940 const uint8_t *gen_ie, uint16_t len)
11941{
11942 uint16_t cur_add_ie_len =
11943 wext_state->assocAddIE.length;
11944
11945 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11946 (wext_state->assocAddIE.length + len)) {
11947 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11948 QDF_ASSERT(0);
11949 return -ENOMEM;
11950 }
11951 memcpy(wext_state->assocAddIE.addIEdata +
11952 cur_add_ie_len, gen_ie, len);
11953 wext_state->assocAddIE.length += len;
11954
11955 wext_state->roamProfile.pAddIEAssoc =
11956 wext_state->assocAddIE.addIEdata;
11957 wext_state->roamProfile.nAddIEAssocLength =
11958 wext_state->assocAddIE.length;
11959 return 0;
11960}
11961
11962/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011963 * wlan_hdd_cfg80211_set_ie() - set IEs
11964 * @pAdapter: Pointer to adapter
11965 * @ie: Pointer ot ie
11966 * @ie: IE length
11967 *
11968 * Return: 0 for success, non-zero for failure
11969 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011970static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011971 size_t ie_len)
11972{
11973 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11974 const uint8_t *genie = ie;
11975 uint16_t remLen = ie_len;
11976#ifdef FEATURE_WLAN_WAPI
11977 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11978 u16 *tmp;
11979 uint16_t akmsuiteCount;
11980 int *akmlist;
11981#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011982 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011983
11984 /* clear previous assocAddIE */
11985 pWextState->assocAddIE.length = 0;
11986 pWextState->roamProfile.bWPSAssociation = false;
11987 pWextState->roamProfile.bOSENAssociation = false;
11988
11989 while (remLen >= 2) {
11990 uint16_t eLen = 0;
11991 uint8_t elementId;
11992 elementId = *genie++;
11993 eLen = *genie++;
11994 remLen -= 2;
11995
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011996 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997
11998 switch (elementId) {
11999 case DOT11F_EID_WPA:
12000 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 -070012001 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012002 return -EINVAL;
12003 } else if (0 ==
12004 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12005 uint16_t curAddIELen =
12006 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012007 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012008
12009 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12010 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012011 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012012 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012013 return -ENOMEM;
12014 }
12015 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12016 memcpy(pWextState->assocAddIE.addIEdata +
12017 curAddIELen, genie - 2, eLen + 2);
12018 pWextState->assocAddIE.length += eLen + 2;
12019
12020 pWextState->roamProfile.bWPSAssociation = true;
12021 pWextState->roamProfile.pAddIEAssoc =
12022 pWextState->assocAddIE.addIEdata;
12023 pWextState->roamProfile.nAddIEAssocLength =
12024 pWextState->assocAddIE.length;
12025 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012026 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 memset(pWextState->WPARSNIE, 0,
12028 MAX_WPA_RSN_IE_LEN);
12029 memcpy(pWextState->WPARSNIE, genie - 2,
12030 (eLen + 2));
12031 pWextState->roamProfile.pWPAReqIE =
12032 pWextState->WPARSNIE;
12033 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12034 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12035 P2P_OUI_TYPE_SIZE))) {
12036 uint16_t curAddIELen =
12037 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012038 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039
12040 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12041 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012042 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012043 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012044 return -ENOMEM;
12045 }
12046 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12047 memcpy(pWextState->assocAddIE.addIEdata +
12048 curAddIELen, genie - 2, eLen + 2);
12049 pWextState->assocAddIE.length += eLen + 2;
12050
12051 pWextState->roamProfile.pAddIEAssoc =
12052 pWextState->assocAddIE.addIEdata;
12053 pWextState->roamProfile.nAddIEAssocLength =
12054 pWextState->assocAddIE.length;
12055 }
12056#ifdef WLAN_FEATURE_WFD
12057 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12058 WFD_OUI_TYPE_SIZE)) &&
12059 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012060 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 pAdapter->device_mode)) {
12062 uint16_t curAddIELen =
12063 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012064 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012065
12066 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12067 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012068 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012069 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070 return -ENOMEM;
12071 }
12072 /* WFD IE is saved to Additional IE ; it should
12073 * be accumulated to handle WPS IE + P2P IE +
12074 * WFD IE */
12075 memcpy(pWextState->assocAddIE.addIEdata +
12076 curAddIELen, genie - 2, eLen + 2);
12077 pWextState->assocAddIE.length += eLen + 2;
12078
12079 pWextState->roamProfile.pAddIEAssoc =
12080 pWextState->assocAddIE.addIEdata;
12081 pWextState->roamProfile.nAddIEAssocLength =
12082 pWextState->assocAddIE.length;
12083 }
12084#endif
12085 /* Appending HS 2.0 Indication Element in Assiciation Request */
12086 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12087 HS20_OUI_TYPE_SIZE))) {
12088 uint16_t curAddIELen =
12089 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012090 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091
12092 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12093 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012094 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012095 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096 return -ENOMEM;
12097 }
12098 memcpy(pWextState->assocAddIE.addIEdata +
12099 curAddIELen, genie - 2, eLen + 2);
12100 pWextState->assocAddIE.length += eLen + 2;
12101
12102 pWextState->roamProfile.pAddIEAssoc =
12103 pWextState->assocAddIE.addIEdata;
12104 pWextState->roamProfile.nAddIEAssocLength =
12105 pWextState->assocAddIE.length;
12106 }
12107 /* Appending OSEN Information Element in Assiciation Request */
12108 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12109 OSEN_OUI_TYPE_SIZE))) {
12110 uint16_t curAddIELen =
12111 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012112 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113
12114 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12115 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012116 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012117 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118 return -ENOMEM;
12119 }
12120 memcpy(pWextState->assocAddIE.addIEdata +
12121 curAddIELen, genie - 2, eLen + 2);
12122 pWextState->assocAddIE.length += eLen + 2;
12123
12124 pWextState->roamProfile.bOSENAssociation = true;
12125 pWextState->roamProfile.pAddIEAssoc =
12126 pWextState->assocAddIE.addIEdata;
12127 pWextState->roamProfile.nAddIEAssocLength =
12128 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012129 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12130 MBO_OUI_TYPE_SIZE))){
12131 hdd_info("Set MBO IE(len %d)", eLen + 2);
12132 status = wlan_hdd_add_assoc_ie(pWextState,
12133 genie - 2, eLen + 2);
12134 if (status)
12135 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 } else {
12137 uint16_t add_ie_len =
12138 pWextState->assocAddIE.length;
12139
12140 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12141
12142 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12143 (pWextState->assocAddIE.length + eLen)) {
12144 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012145 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146 return -ENOMEM;
12147 }
12148
12149 memcpy(pWextState->assocAddIE.addIEdata +
12150 add_ie_len, genie - 2, eLen + 2);
12151 pWextState->assocAddIE.length += eLen + 2;
12152
12153 pWextState->roamProfile.pAddIEAssoc =
12154 pWextState->assocAddIE.addIEdata;
12155 pWextState->roamProfile.nAddIEAssocLength =
12156 pWextState->assocAddIE.length;
12157 }
12158 break;
12159 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012160 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012161 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12162 memcpy(pWextState->WPARSNIE, genie - 2,
12163 (eLen + 2));
12164 pWextState->roamProfile.pRSNReqIE =
12165 pWextState->WPARSNIE;
12166 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12167 break;
12168 /*
12169 * Appending Extended Capabilities with Interworking bit set
12170 * in Assoc Req.
12171 *
12172 * In assoc req this EXT Cap will only be taken into account if
12173 * interworkingService bit is set to 1. Currently
12174 * driver is only interested in interworkingService capability
12175 * from supplicant. If in future any other EXT Cap info is
12176 * required from supplicat, it needs to be handled while
12177 * sending Assoc Req in LIM.
12178 */
12179 case DOT11F_EID_EXTCAP:
12180 {
12181 uint16_t curAddIELen =
12182 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012183 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012184
12185 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12186 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012187 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012188 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012189 return -ENOMEM;
12190 }
12191 memcpy(pWextState->assocAddIE.addIEdata +
12192 curAddIELen, genie - 2, eLen + 2);
12193 pWextState->assocAddIE.length += eLen + 2;
12194
12195 pWextState->roamProfile.pAddIEAssoc =
12196 pWextState->assocAddIE.addIEdata;
12197 pWextState->roamProfile.nAddIEAssocLength =
12198 pWextState->assocAddIE.length;
12199 break;
12200 }
12201#ifdef FEATURE_WLAN_WAPI
12202 case WLAN_EID_WAPI:
12203 /* Setting WAPI Mode to ON=1 */
12204 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012205 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012206 tmp = (u16 *) ie;
12207 tmp = tmp + 2; /* Skip element Id and Len, Version */
12208 akmsuiteCount = WPA_GET_LE16(tmp);
12209 tmp = tmp + 1;
12210 akmlist = (int *)(tmp);
12211 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12212 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12213 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012214 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012215 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012216 return -EINVAL;
12217 }
12218
12219 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012220 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221 pAdapter->wapi_info.wapiAuthMode =
12222 WAPI_AUTH_MODE_PSK;
12223 }
12224 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012225 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 pAdapter->wapi_info.wapiAuthMode =
12227 WAPI_AUTH_MODE_CERT;
12228 }
12229 break;
12230#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012231 case DOT11F_EID_SUPPOPERATINGCLASSES:
12232 {
12233 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12234 status = wlan_hdd_add_assoc_ie(pWextState,
12235 genie - 2, eLen + 2);
12236 if (status)
12237 return status;
12238 break;
12239 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012240 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012241 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012242 /* when Unknown IE is received we should break and continue
12243 * to the next IE in the buffer instead we were returning
12244 * so changing this to break */
12245 break;
12246 }
12247 genie += eLen;
12248 remLen -= eLen;
12249 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012250 return 0;
12251}
12252
12253/**
12254 * hdd_is_wpaie_present() - check for WPA ie
12255 * @ie: Pointer to ie
12256 * @ie_len: Ie length
12257 *
12258 * Parse the received IE to find the WPA IE
12259 *
12260 * Return: true if wpa ie is found else false
12261 */
12262static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12263{
12264 uint8_t eLen = 0;
12265 uint16_t remLen = ie_len;
12266 uint8_t elementId = 0;
12267
12268 while (remLen >= 2) {
12269 elementId = *ie++;
12270 eLen = *ie++;
12271 remLen -= 2;
12272 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012273 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274 return false;
12275 }
12276 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12277 /* OUI - 0x00 0X50 0XF2
12278 * WPA Information Element - 0x01
12279 * WPA version - 0x01
12280 */
12281 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12282 return true;
12283 }
12284 ie += eLen;
12285 remLen -= eLen;
12286 }
12287 return false;
12288}
12289
12290/**
12291 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12292 * @pAdapter: Pointer to adapter
12293 * @req: Pointer to security parameters
12294 *
12295 * Return: 0 for success, non-zero for failure
12296 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012297static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12298 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299{
12300 int status = 0;
12301 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12302 ENTER();
12303
12304 /*set wpa version */
12305 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12306
12307 if (req->crypto.wpa_versions) {
12308 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12309 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12310 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12311 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12312 }
12313 }
12314
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012315 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012316
12317 /*set authentication type */
12318 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12319
12320 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012321 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 return status;
12323 }
12324
12325 /*set key mgmt type */
12326 if (req->crypto.n_akm_suites) {
12327 status =
12328 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12329 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012330 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 return status;
12332 }
12333 }
12334
12335 /*set pairwise cipher type */
12336 if (req->crypto.n_ciphers_pairwise) {
12337 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12338 req->crypto.
12339 ciphers_pairwise[0],
12340 true);
12341 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012342 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 return status;
12344 }
12345 } else {
12346 /*Reset previous cipher suite to none */
12347 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12348 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012349 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012350 return status;
12351 }
12352 }
12353
12354 /*set group cipher type */
12355 status =
12356 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12357 false);
12358
12359 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012360 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 return status;
12362 }
12363#ifdef WLAN_FEATURE_11W
12364 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12365#endif
12366
12367 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12368 if (req->ie_len) {
12369 status =
12370 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12371 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012372 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373 return status;
12374 }
12375 }
12376
12377 /*incase of WEP set default key information */
12378 if (req->key && req->key_len) {
12379 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12380 || (WLAN_CIPHER_SUITE_WEP104 ==
12381 req->crypto.ciphers_pairwise[0])
12382 ) {
12383 if (IW_AUTH_KEY_MGMT_802_1X
12384 ==
12385 (pWextState->
12386 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012387 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 return -EOPNOTSUPP;
12389 } else {
12390 u8 key_len = req->key_len;
12391 u8 key_idx = req->key_idx;
12392
12393 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12394 key_len)
12395 && (CSR_MAX_NUM_KEY > key_idx)
12396 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012397 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012398 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012399 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 Keys.
12401 KeyMaterial[key_idx][0],
12402 req->key, key_len);
12403 pWextState->roamProfile.Keys.
12404 KeyLength[key_idx] = (u8) key_len;
12405 pWextState->roamProfile.Keys.
12406 defaultIndex = (u8) key_idx;
12407 }
12408 }
12409 }
12410 }
12411
12412 return status;
12413}
12414
12415/**
12416 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12417 * @pAdapter: Pointer to adapter
12418 *
12419 * This function is used to disconnect from previous connection
12420 *
12421 * Return: 0 for success, non-zero for failure
12422 */
12423static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12424{
12425 unsigned long rc;
12426 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012427 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428
12429 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12430
Jeff Johnson9edf9572016-10-03 15:24:49 -070012431 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012432 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12433 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12434 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435 hdd_conn_set_connection_state(pAdapter,
12436 eConnectionState_Disconnecting);
12437 /* Issue disconnect to CSR */
12438 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012439
12440 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12441 pAdapter->sessionId,
12442 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12443 /*
12444 * Wait here instead of returning directly, this will block the
12445 * next connect command and allow processing of the scan for
12446 * ssid and the previous connect command in CSR. Else we might
12447 * hit some race conditions leading to SME and HDD out of sync.
12448 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012449 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012450 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12451 } else if (0 != status) {
12452 hdd_err("csrRoamDisconnect failure, returned %d",
12453 (int)status);
12454 pHddStaCtx->staDebugState = status;
12455 result = -EINVAL;
12456 goto disconnected;
12457 }
12458
12459 rc = wait_for_completion_timeout(
12460 &pAdapter->disconnect_comp_var,
12461 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012462 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012463 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12464 pAdapter->sessionId, pHddStaCtx->staDebugState);
12465 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012466 }
12467 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012468 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012470 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012472 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012474 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475 }
12476 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012477disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012478 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12479 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480}
12481
12482/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012483 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12484 * @adapter: Pointer to the HDD adapter
12485 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012486 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012487 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012488 * This function will start reassociation if prev_bssid is set and bssid/
12489 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012490 *
Naveen Rawat07332902016-07-27 09:13:17 -070012491 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012492 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012493#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12494 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012495static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12496 struct cfg80211_connect_params *req,
12497 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012498{
Naveen Rawat07332902016-07-27 09:13:17 -070012499 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012500 const uint8_t *bssid = NULL;
12501 uint16_t channel = 0;
12502
12503 if (req->bssid)
12504 bssid = req->bssid;
12505 else if (req->bssid_hint)
12506 bssid = req->bssid_hint;
12507
12508 if (req->channel)
12509 channel = req->channel->hw_value;
12510 else if (req->channel_hint)
12511 channel = req->channel_hint->hw_value;
12512
12513 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012514 reassoc = true;
12515 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012516 channel, MAC_ADDR_ARRAY(bssid));
12517 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012518 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012519 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012520 }
Naveen Rawat07332902016-07-27 09:13:17 -070012521 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012522}
12523#else
Naveen Rawat07332902016-07-27 09:13:17 -070012524static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12525 struct cfg80211_connect_params *req,
12526 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012527{
Naveen Rawat07332902016-07-27 09:13:17 -070012528 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012529}
12530#endif
12531
12532/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12534 * @wiphy: Pointer to wiphy
12535 * @dev: Pointer to network device
12536 * @req: Pointer to cfg80211 connect request
12537 *
12538 * This function is used to start the association process
12539 *
12540 * Return: 0 for success, non-zero for failure
12541 */
12542static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12543 struct net_device *ndev,
12544 struct cfg80211_connect_params *req)
12545{
12546 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012547 u16 channel;
12548#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12549 const u8 *bssid_hint = req->bssid_hint;
12550#else
12551 const u8 *bssid_hint = NULL;
12552#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012553 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12554 hdd_context_t *pHddCtx;
12555
12556 ENTER();
12557
Anurag Chouhan6d760662016-02-20 16:05:43 +053012558 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012559 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012560 return -EINVAL;
12561 }
12562
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012563 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12564 hdd_err("invalid session id: %d", pAdapter->sessionId);
12565 return -EINVAL;
12566 }
12567
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012568 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012569 TRACE_CODE_HDD_CFG80211_CONNECT,
12570 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012571 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 hdd_device_mode_to_string(pAdapter->device_mode),
12573 pAdapter->device_mode);
12574
Krunal Sonib4326f22016-03-10 13:05:51 -080012575 if (pAdapter->device_mode != QDF_STA_MODE &&
12576 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012577 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012578 hdd_device_mode_to_string(pAdapter->device_mode),
12579 pAdapter->device_mode);
12580 return -EINVAL;
12581 }
12582
12583 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12584 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012585 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012586 return -EINVAL;
12587 }
12588
12589 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012590 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012591 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012592
Naveen Rawat07332902016-07-27 09:13:17 -070012593 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012594 return status;
12595
Agrawal Ashishf156e942016-08-04 14:54:47 +053012596 wlan_hdd_disable_roaming(pAdapter);
12597
12598 /* Try disconnecting if already in connected state */
12599 status = wlan_hdd_try_disconnect(pAdapter);
12600 if (0 > status) {
12601 hdd_err("Failed to disconnect the existing connection");
12602 return -EALREADY;
12603 }
12604
12605 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012607 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012608 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012609 pAdapter->device_mode),
12610 req->channel->hw_value, HW_MODE_20_MHZ)) {
12611 hdd_err("This concurrency combination is not allowed");
12612 return -ECONNREFUSED;
12613 }
12614 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012615 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012616 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12618 hdd_err("This concurrency combination is not allowed");
12619 return -ECONNREFUSED;
12620 }
12621 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 /*initialise security parameters */
12624 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12625
12626 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012627 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628 return status;
12629 }
12630
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012631 if (req->channel)
12632 channel = req->channel->hw_value;
12633 else
12634 channel = 0;
12635 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12636 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012637 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012638 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012639 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640 return status;
12641 }
12642 EXIT();
12643 return status;
12644}
12645
12646/**
12647 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12648 * @wiphy: Pointer to wiphy
12649 * @dev: Pointer to network device
12650 * @req: Pointer to cfg80211 connect request
12651 *
12652 * Return: 0 for success, non-zero for failure
12653 */
12654static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12655 struct net_device *ndev,
12656 struct cfg80211_connect_params *req)
12657{
12658 int ret;
12659 cds_ssr_protect(__func__);
12660 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12661 cds_ssr_unprotect(__func__);
12662
12663 return ret;
12664}
12665
12666/**
12667 * wlan_hdd_disconnect() - hdd disconnect api
12668 * @pAdapter: Pointer to adapter
12669 * @reason: Disconnect reason code
12670 *
12671 * This function is used to issue a disconnect request to SME
12672 *
12673 * Return: 0 for success, non-zero for failure
12674 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012675static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676{
12677 int status, result = 0;
12678 unsigned long rc;
12679 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12680 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12681
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012682 ENTER();
12683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012684 status = wlan_hdd_validate_context(pHddCtx);
12685
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012686 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012687 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012688
12689 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012690 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12692 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012693 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012694 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12695 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12696
12697 /*issue disconnect */
12698
12699 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12700 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012701 /*
12702 * Wait here instead of returning directly, this will block the next
12703 * connect command and allow processing of the scan for ssid and
12704 * the previous connect command in CSR. Else we might hit some
12705 * race conditions leading to SME and HDD out of sync.
12706 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012707 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012708 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012709 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012710 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711 (int)status);
12712 pHddStaCtx->staDebugState = status;
12713 result = -EINVAL;
12714 goto disconnected;
12715 }
12716 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12717 msecs_to_jiffies
12718 (WLAN_WAIT_TIME_DISCONNECT));
12719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012720 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012721 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722 result = -ETIMEDOUT;
12723 }
12724disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12726#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12727 /* Sending disconnect event to userspace for kernel version < 3.11
12728 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12729 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012730 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012731 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12732 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733#endif
12734
12735 return result;
12736}
12737
12738/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012739 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12740 * @reason: ieee80211 reason code.
12741 *
12742 * This utility function helps log string conversion of reason code.
12743 *
12744 * Return: string conversion of reason code, if match found;
12745 * "Unknown" otherwise.
12746 */
12747static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12748{
12749 switch (reason) {
12750 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12751 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12752 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12753 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12754 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12755 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12756 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12757 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12758 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12759 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12760 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12761 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12762 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12763 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12764 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12765 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12766 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12767 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12768 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12769 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12770 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12771 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12772 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12773 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12774 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12775 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12776 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12777 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12778 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12779 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12780 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12781 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12782 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12783 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12784 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12785 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12786 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12787 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12788 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12789 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12790 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12791 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12792 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12793 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12794 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12795 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12796 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12797 default:
12798 return "Unknown";
12799 }
12800}
12801
12802/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012803 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12804 * @wiphy: Pointer to wiphy
12805 * @dev: Pointer to network device
12806 * @reason: Disconnect reason code
12807 *
12808 * This function is used to issue a disconnect request to SME
12809 *
12810 * Return: 0 for success, non-zero for failure
12811 */
12812static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12813 struct net_device *dev, u16 reason)
12814{
12815 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12816 int status;
12817 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12818 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12819#ifdef FEATURE_WLAN_TDLS
12820 uint8_t staIdx;
12821#endif
12822
12823 ENTER();
12824
Anurag Chouhan6d760662016-02-20 16:05:43 +053012825 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012826 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012827 return -EINVAL;
12828 }
12829
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012830 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12831 hdd_err("invalid session id: %d", pAdapter->sessionId);
12832 return -EINVAL;
12833 }
12834
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012835 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012836 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12837 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012838 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839 hdd_device_mode_to_string(pAdapter->device_mode),
12840 pAdapter->device_mode, reason);
12841
12842 status = wlan_hdd_validate_context(pHddCtx);
12843
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012844 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012845 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846
12847 /* Issue disconnect request to SME, if station is in connected state */
12848 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12849 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12850 eCsrRoamDisconnectReason reasonCode =
12851 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12852 hdd_scaninfo_t *pScanInfo;
12853
12854 switch (reason) {
12855 case WLAN_REASON_MIC_FAILURE:
12856 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12857 break;
12858
12859 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12860 case WLAN_REASON_DISASSOC_AP_BUSY:
12861 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12862 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12863 break;
12864
12865 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12866 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12867 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12868 break;
12869
12870 case WLAN_REASON_DEAUTH_LEAVING:
12871 reasonCode =
12872 pHddCtx->config->
12873 gEnableDeauthToDisassocMap ?
12874 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12875 eCSR_DISCONNECT_REASON_DEAUTH;
12876 break;
12877 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12878 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12879 break;
12880 default:
12881 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12882 break;
12883 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012884 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012885 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012886 pScanInfo = &pAdapter->scan_info;
12887 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012888 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012889 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12890 eCSR_SCAN_ABORT_DEFAULT);
12891 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012892 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012893#ifdef FEATURE_WLAN_TDLS
12894 /* First clean up the tdls peers if any */
12895 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12896 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12897 pAdapter->sessionId)
12898 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12899 uint8_t *mac;
12900 mac =
12901 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012902 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12903 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 pHddCtx->tdlsConnInfo[staIdx].staId,
12905 pAdapter->sessionId,
12906 MAC_ADDR_ARRAY(mac));
12907 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12908 (pAdapter),
12909 pAdapter->sessionId, mac);
12910 }
12911 }
12912#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012913 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012914 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012915 hdd_info("Disconnect request from user space with reason: %s",
12916 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12918 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012919 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 return -EINVAL;
12921 }
12922 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012923 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012924 pHddStaCtx->conn_info.connState);
12925 }
12926
12927 return status;
12928}
12929
12930/**
12931 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12932 * @wiphy: Pointer to wiphy
12933 * @dev: Pointer to network device
12934 * @reason: Disconnect reason code
12935 *
12936 * Return: 0 for success, non-zero for failure
12937 */
12938static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12939 struct net_device *dev, u16 reason)
12940{
12941 int ret;
12942 cds_ssr_protect(__func__);
12943 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12944 cds_ssr_unprotect(__func__);
12945
12946 return ret;
12947}
12948
12949/**
12950 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12951 * @pAdapter: Pointer to adapter
12952 * @param: Pointer to IBSS parameters
12953 *
12954 * This function is used to initialize the security settings in IBSS mode
12955 *
12956 * Return: 0 for success, non-zero for failure
12957 */
12958static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12959 struct cfg80211_ibss_params
12960 *params)
12961{
12962 int status = 0;
12963 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12964 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12965 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12966
12967 ENTER();
12968
12969 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012970 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 pHddStaCtx->ibss_enc_key_installed = 0;
12972
12973 if (params->ie_len && (NULL != params->ie)) {
12974 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12975 params->ie_len, WLAN_EID_RSN)) {
12976 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12977 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12978 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12979 tDot11fIEWPA dot11WPAIE;
12980 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12981 u8 *ie;
12982
12983 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12984 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12985 params->ie_len,
12986 DOT11F_EID_WPA);
12987 if (NULL != ie) {
12988 pWextState->wpaVersion =
12989 IW_AUTH_WPA_VERSION_WPA;
12990 /* Unpack the WPA IE */
12991 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12992 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12993 &ie[2 + 4],
12994 ie[1] - 4, &dot11WPAIE);
12995 /*Extract the multicast cipher, the encType for unicast
12996 cipher for wpa-none is none */
12997 encryptionType =
12998 hdd_translate_wpa_to_csr_encryption_type
12999 (dot11WPAIE.multicast_cipher);
13000 }
13001 }
13002
13003 status =
13004 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13005 params->ie_len);
13006
13007 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013008 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013009 return status;
13010 }
13011 }
13012
13013 pWextState->roamProfile.AuthType.authType[0] =
13014 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13015
13016 if (params->privacy) {
13017 /* Security enabled IBSS, At this time there is no information
13018 * available about the security paramters, so initialise the
13019 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13020 * The correct security parameters will be updated later in
13021 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13022 * set inorder enable privacy bit in beacons
13023 */
13024
13025 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13026 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013027 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13029 pWextState->roamProfile.EncryptionType.numEntries = 1;
13030 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13031 encryptionType;
13032 return status;
13033}
13034
13035/**
13036 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13037 * @wiphy: Pointer to wiphy
13038 * @dev: Pointer to network device
13039 * @param: Pointer to IBSS join parameters
13040 *
13041 * This function is used to create/join an IBSS network
13042 *
13043 * Return: 0 for success, non-zero for failure
13044 */
13045static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13046 struct net_device *dev,
13047 struct cfg80211_ibss_params *params)
13048{
13049 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13050 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13051 tCsrRoamProfile *pRoamProfile;
13052 int status;
13053 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13054 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013055 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013057
13058 ENTER();
13059
Anurag Chouhan6d760662016-02-20 16:05:43 +053013060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013061 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062 return -EINVAL;
13063 }
13064
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013065 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13066 hdd_err("invalid session id: %d", pAdapter->sessionId);
13067 return -EINVAL;
13068 }
13069
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013070 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013071 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13072 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013073 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 hdd_device_mode_to_string(pAdapter->device_mode),
13075 pAdapter->device_mode);
13076
13077 status = wlan_hdd_validate_context(pHddCtx);
13078
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013079 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013080 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013081
13082 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013083 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13085 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13086 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13087 int indx;
13088
13089 /* Get channel number */
13090 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013091 params->
13092 chandef.
13093 chan->
13094 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013095
13096 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13097 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013098 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099 return -EOPNOTSUPP;
13100 }
13101
13102 for (indx = 0; indx < numChans; indx++) {
13103 if (channelNum == validChan[indx]) {
13104 break;
13105 }
13106 }
13107 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013108 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 return -EINVAL;
13110 }
13111 }
13112
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013113 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013114 HW_MODE_20_MHZ)) {
13115 hdd_err("This concurrency combination is not allowed");
13116 return -ECONNREFUSED;
13117 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118
Krunal Soni3091bcc2016-06-23 12:28:21 -070013119 status = qdf_reset_connection_update();
13120 if (!QDF_IS_STATUS_SUCCESS(status))
13121 hdd_err("ERR: clear event failed");
13122
13123 status = cds_current_connections_update(pAdapter->sessionId,
13124 channelNum,
13125 SIR_UPDATE_REASON_JOIN_IBSS);
13126 if (QDF_STATUS_E_FAILURE == status) {
13127 hdd_err("ERROR: connections update failed!!");
13128 return -EINVAL;
13129 }
13130
13131 if (QDF_STATUS_SUCCESS == status) {
13132 status = qdf_wait_for_connection_update();
13133 if (!QDF_IS_STATUS_SUCCESS(status)) {
13134 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013135 return -EINVAL;
13136 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013137 }
13138
13139 /*Try disconnecting if already in connected state */
13140 status = wlan_hdd_try_disconnect(pAdapter);
13141 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013142 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013143 return -EALREADY;
13144 }
13145
13146 pRoamProfile = &pWextState->roamProfile;
13147
13148 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013149 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013150 return -EINVAL;
13151 }
13152
13153 /* enable selected protection checks in IBSS mode */
13154 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13155
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013156 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13158 pHddCtx->config->
13159 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013160 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 }
13162
13163 /* BSSID is provided by upper layers hence no need to AUTO generate */
13164 if (NULL != params->bssid) {
13165 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013166 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013167 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013168 return -EIO;
13169 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013170 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13172 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013173 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013174 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 return -EIO;
13176 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013177 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013178 }
13179 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13180 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13181 pRoamProfile->beaconInterval = params->beacon_interval;
13182 else {
13183 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013184 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013185 params->beacon_interval, pRoamProfile->beaconInterval);
13186 }
13187
13188 /* Set Channel */
13189 if (channelNum) {
13190 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013191 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 pRoamProfile->ChannelInfo.numOfChannels = 1;
13193 pHddStaCtx->conn_info.operationChannel = channelNum;
13194 pRoamProfile->ChannelInfo.ChannelList =
13195 &pHddStaCtx->conn_info.operationChannel;
13196 }
13197
13198 /* Initialize security parameters */
13199 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13200 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013201 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013202 return status;
13203 }
13204
13205 /* Issue connect start */
13206 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13207 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013208 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013210 operationChannel,
13211 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013212
13213 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013214 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013215 return status;
13216 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013217 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013218 return 0;
13219}
13220
13221/**
13222 * wlan_hdd_cfg80211_join_ibss() - join ibss
13223 * @wiphy: Pointer to wiphy
13224 * @dev: Pointer to network device
13225 * @param: Pointer to IBSS join parameters
13226 *
13227 * This function is used to create/join an IBSS network
13228 *
13229 * Return: 0 for success, non-zero for failure
13230 */
13231static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13232 struct net_device *dev,
13233 struct cfg80211_ibss_params *params)
13234{
13235 int ret = 0;
13236
13237 cds_ssr_protect(__func__);
13238 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13239 cds_ssr_unprotect(__func__);
13240
13241 return ret;
13242}
13243
13244/**
13245 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13246 * @wiphy: Pointer to wiphy
13247 * @dev: Pointer to network device
13248 *
13249 * This function is used to leave an IBSS network
13250 *
13251 * Return: 0 for success, non-zero for failure
13252 */
13253static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13254 struct net_device *dev)
13255{
13256 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13257 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13258 tCsrRoamProfile *pRoamProfile;
13259 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13260 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013261 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013262 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013263 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013264
13265 ENTER();
13266
Anurag Chouhan6d760662016-02-20 16:05:43 +053013267 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013268 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 return -EINVAL;
13270 }
13271
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013272 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13273 hdd_err("invalid session id: %d", pAdapter->sessionId);
13274 return -EINVAL;
13275 }
13276
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013277 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13279 pAdapter->sessionId,
13280 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13281 status = wlan_hdd_validate_context(pHddCtx);
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
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013285 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 hdd_device_mode_to_string(pAdapter->device_mode),
13287 pAdapter->device_mode);
13288 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013289 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 return -EIO;
13291 }
13292
13293 pRoamProfile = &pWextState->roamProfile;
13294
13295 /* Issue disconnect only if interface type is set to IBSS */
13296 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013297 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013298 return -EINVAL;
13299 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013300 /* Clearing add IE of beacon */
13301 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13302 sizeof(tSirMacAddr));
13303 updateIE.smeSessionId = pAdapter->sessionId;
13304 updateIE.ieBufferlength = 0;
13305 updateIE.pAdditionIEBuffer = NULL;
13306 updateIE.append = true;
13307 updateIE.notify = true;
13308 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13309 &updateIE,
13310 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013311 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013312 }
13313
13314 /* Reset WNI_CFG_PROBE_RSP Flags */
13315 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013316
13317 /* Issue Disconnect request */
13318 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13319 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13320 pAdapter->sessionId,
13321 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013322 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013323 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 hal_status);
13325 return -EAGAIN;
13326 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013327
13328 /* wait for mc thread to cleanup and then return to upper stack
13329 * so by the time upper layer calls the change interface, we are
13330 * all set to proceed further
13331 */
13332 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13333 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13334 if (!rc) {
13335 hdd_err("Failed to disconnect, timed out");
13336 return -ETIMEDOUT;
13337 }
13338
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013339 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340 return 0;
13341}
13342
13343/**
13344 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13345 * @wiphy: Pointer to wiphy
13346 * @dev: Pointer to network device
13347 *
13348 * This function is used to leave an IBSS network
13349 *
13350 * Return: 0 for success, non-zero for failure
13351 */
13352static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13353 struct net_device *dev)
13354{
13355 int ret = 0;
13356
13357 cds_ssr_protect(__func__);
13358 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13359 cds_ssr_unprotect(__func__);
13360
13361 return ret;
13362}
13363
13364/**
13365 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13366 * @wiphy: Pointer to wiphy
13367 * @changed: Parameters changed
13368 *
13369 * This function is used to set the phy parameters. RTS Threshold/FRAG
13370 * Threshold/Retry Count etc.
13371 *
13372 * Return: 0 for success, non-zero for failure
13373 */
13374static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13375 u32 changed)
13376{
13377 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13378 tHalHandle hHal = pHddCtx->hHal;
13379 int status;
13380
13381 ENTER();
13382
Anurag Chouhan6d760662016-02-20 16:05:43 +053013383 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013384 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 return -EINVAL;
13386 }
13387
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013388 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013389 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13390 NO_SESSION, wiphy->rts_threshold));
13391 status = wlan_hdd_validate_context(pHddCtx);
13392
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013393 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013394 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013395
13396 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13397 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13398 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13399
13400 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13401 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013402 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 rts_threshold);
13404 return -EINVAL;
13405 }
13406
13407 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13408 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013409 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410 rts_threshold);
13411 return -EIO;
13412 }
13413
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013414 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013415 }
13416
13417 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13418 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13419 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13420 wiphy->frag_threshold;
13421
13422 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13423 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013424 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 frag_threshold);
13426 return -EINVAL;
13427 }
13428
13429 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13430 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013431 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 frag_threshold);
13433 return -EIO;
13434 }
13435
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013436 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437 }
13438
13439 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13440 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13441 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13442 wiphy->retry_short : wiphy->retry_long;
13443
13444 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13445 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013446 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447 return -EINVAL;
13448 }
13449
13450 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13451 if (0 != sme_cfg_set_int(hHal,
13452 WNI_CFG_LONG_RETRY_LIMIT,
13453 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013454 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 retry_value);
13456 return -EIO;
13457 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013458 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13460 if (0 != sme_cfg_set_int(hHal,
13461 WNI_CFG_SHORT_RETRY_LIMIT,
13462 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013463 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 retry_value);
13465 return -EIO;
13466 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013467 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013468 }
13469 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013470 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471 return 0;
13472}
13473
13474/**
13475 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13476 * @wiphy: Pointer to wiphy
13477 * @changed: Parameters changed
13478 *
13479 * Return: 0 for success, non-zero for failure
13480 */
13481static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13482{
13483 int ret;
13484
13485 cds_ssr_protect(__func__);
13486 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13487 cds_ssr_unprotect(__func__);
13488
13489 return ret;
13490}
13491
13492/**
13493 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13494 * key
13495 * @wiphy: Pointer to wiphy
13496 * @dev: Pointer to network device
13497 * @key_index: Key index
13498 *
13499 * Return: 0
13500 */
13501static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13502 struct net_device *netdev,
13503 u8 key_index)
13504{
13505 ENTER();
13506 return 0;
13507}
13508
13509/**
13510 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13511 * wlan_hdd_set_default_mgmt_key
13512 * @wiphy: pointer to wiphy
13513 * @netdev: pointer to net_device structure
13514 * @key_index: key index
13515 *
13516 * Return: 0 on success, error number on failure
13517 */
13518static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13519 struct net_device *netdev,
13520 u8 key_index)
13521{
13522 int ret;
13523
13524 cds_ssr_protect(__func__);
13525 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13526 cds_ssr_unprotect(__func__);
13527
13528 return ret;
13529}
13530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531/**
13532 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13533 * @wiphy: Pointer to wiphy
13534 * @dev: Pointer to network device
13535 * @params: Pointer to tx queue parameters
13536 *
13537 * Return: 0
13538 */
13539static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13540 struct net_device *dev,
13541 struct ieee80211_txq_params *params)
13542{
13543 ENTER();
13544 return 0;
13545}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546
13547/**
13548 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13549 * @wiphy: pointer to wiphy
13550 * @netdev: pointer to net_device structure
13551 * @params: pointer to ieee80211_txq_params
13552 *
13553 * Return: 0 on success, error number on failure
13554 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13556 struct net_device *dev,
13557 struct ieee80211_txq_params *params)
13558{
13559 int ret;
13560
13561 cds_ssr_protect(__func__);
13562 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13563 cds_ssr_unprotect(__func__);
13564
13565 return ret;
13566}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567
13568/**
13569 * __wlan_hdd_cfg80211_del_station() - delete station v2
13570 * @wiphy: Pointer to wiphy
13571 * @param: Pointer to delete station parameter
13572 *
13573 * Return: 0 for success, non-zero for failure
13574 */
13575static
13576int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13577 struct net_device *dev,
13578 struct tagCsrDelStaParams *pDelStaParams)
13579{
13580 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13581 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013582 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 hdd_hostapd_state_t *hapd_state;
13584 int status;
13585 uint8_t staId;
13586 uint8_t *mac;
13587
13588 ENTER();
13589
Anurag Chouhan6d760662016-02-20 16:05:43 +053013590 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013591 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013592 return -EINVAL;
13593 }
13594
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013595 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13596 hdd_err("invalid session id: %d", pAdapter->sessionId);
13597 return -EINVAL;
13598 }
13599
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013600 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601 TRACE_CODE_HDD_CFG80211_DEL_STA,
13602 pAdapter->sessionId, pAdapter->device_mode));
13603
13604 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13605 status = wlan_hdd_validate_context(pHddCtx);
13606
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013607 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013608 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013609
13610 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13611
Krunal Sonib4326f22016-03-10 13:05:51 -080013612 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13613 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614
13615 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13616 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013617 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618 return 0;
13619 }
13620
Anurag Chouhanc5548422016-02-24 18:33:27 +053013621 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013622 uint16_t i;
13623 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13624 if ((pAdapter->aStaInfo[i].isUsed) &&
13625 (!pAdapter->aStaInfo[i].
13626 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013627 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013628 mac,
13629 pAdapter->aStaInfo[i].
13630 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013631 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13633 hdd_ipa_wlan_evt(pAdapter,
13634 pAdapter->
13635 aStaInfo[i].
13636 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013637 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 mac);
13639 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013640 hdd_notice("Delete STA with MAC::"
13641 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013642 MAC_ADDR_ARRAY(mac));
13643
13644 if (pHddCtx->dev_dfs_cac_status ==
13645 DFS_CAC_IN_PROGRESS)
13646 goto fn_end;
13647
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013648 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013650 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013651 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013652 hdd_softap_sta_deauth(pAdapter,
13653 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013654 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 pAdapter->aStaInfo[i].
13656 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013657 qdf_status =
13658 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013659 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013661 if (!QDF_IS_STATUS_SUCCESS(
13662 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013663 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013664 }
13665 }
13666 }
13667 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013668 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013669 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013670 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013672 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013673 hdd_notice("Skip DEL STA as this is not used::"
13674 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013675 MAC_ADDR_ARRAY(mac));
13676 return -ENOENT;
13677 }
13678
13679 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13680 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013681 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682 }
13683
13684 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13685 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013686 hdd_notice("Skip DEL STA as deauth is in progress::"
13687 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688 MAC_ADDR_ARRAY(mac));
13689 return -ENOENT;
13690 }
13691
13692 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13693
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013694 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695 MAC_ADDR_ARRAY(mac));
13696
13697 /* Case: SAP in ACS selected DFS ch and client connected
13698 * Now Radar detected. Then if random channel is another
13699 * DFS ch then new CAC is initiated and no TX allowed.
13700 * So do not send any mgmt frames as it will timeout
13701 * during CAC.
13702 */
13703
13704 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13705 goto fn_end;
13706
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013707 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013708 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13709 (pAdapter), pAdapter->sessionId,
13710 (uint8_t *)&pDelStaParams->peerMacAddr,
13711 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013712 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013714 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013715 pAdapter->aStaInfo[staId].isDeauthInProgress =
13716 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013717 hdd_notice("STA removal failed for ::"
13718 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 MAC_ADDR_ARRAY(mac));
13720 return -ENOENT;
13721 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013722 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013723 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013725 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013726 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727 }
13728 }
13729 }
13730
13731fn_end:
13732 EXIT();
13733 return 0;
13734}
13735
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013736#if defined(USE_CFG80211_DEL_STA_V2)
13737/**
13738 * wlan_hdd_del_station() - delete station wrapper
13739 * @adapter: pointer to the hdd adapter
13740 *
13741 * Return: None
13742 */
13743void wlan_hdd_del_station(hdd_adapter_t *adapter)
13744{
13745 struct station_del_parameters del_sta;
13746 del_sta.mac = NULL;
13747 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13748 del_sta.reason_code = eCsrForcedDeauthSta;
13749
13750 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13751 &del_sta);
13752}
13753#else
13754void wlan_hdd_del_station(hdd_adapter_t *adapter)
13755{
13756 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13757}
13758#endif
13759
13760#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013761/**
13762 * wlan_hdd_cfg80211_del_station() - delete station v2
13763 * @wiphy: Pointer to wiphy
13764 * @param: Pointer to delete station parameter
13765 *
13766 * Return: 0 for success, non-zero for failure
13767 */
13768int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13769 struct net_device *dev,
13770 struct station_del_parameters *param)
13771#else
13772/**
13773 * wlan_hdd_cfg80211_del_station() - delete station
13774 * @wiphy: Pointer to wiphy
13775 * @mac: Pointer to station mac address
13776 *
13777 * Return: 0 for success, non-zero for failure
13778 */
13779#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13780int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13781 struct net_device *dev,
13782 const uint8_t *mac)
13783#else
13784int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13785 struct net_device *dev,
13786 uint8_t *mac)
13787#endif
13788#endif
13789{
13790 int ret;
13791 struct tagCsrDelStaParams delStaParams;
13792
13793 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013794#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013795 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013796 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013797 return -EINVAL;
13798 }
13799 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13800 param->subtype, &delStaParams);
13801#else
13802 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13803 (SIR_MAC_MGMT_DEAUTH >> 4),
13804 &delStaParams);
13805#endif
13806 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13807 cds_ssr_unprotect(__func__);
13808
13809 return ret;
13810}
13811
13812/**
13813 * __wlan_hdd_cfg80211_add_station() - add station
13814 * @wiphy: Pointer to wiphy
13815 * @mac: Pointer to station mac address
13816 * @pmksa: Pointer to add station parameter
13817 *
13818 * Return: 0 for success, non-zero for failure
13819 */
13820static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13821 struct net_device *dev,
13822 const uint8_t *mac,
13823 struct station_parameters *params)
13824{
13825 int status = -EPERM;
13826#ifdef FEATURE_WLAN_TDLS
13827 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13828 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13829 u32 mask, set;
13830
13831 ENTER();
13832
Anurag Chouhan6d760662016-02-20 16:05:43 +053013833 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013834 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 return -EINVAL;
13836 }
13837
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013838 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13839 hdd_err("invalid session id: %d", pAdapter->sessionId);
13840 return -EINVAL;
13841 }
13842
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013843 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013844 TRACE_CODE_HDD_CFG80211_ADD_STA,
13845 pAdapter->sessionId, params->listen_interval));
13846
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013847 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013848 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849
13850 mask = params->sta_flags_mask;
13851
13852 set = params->sta_flags_set;
13853
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013854 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 MAC_ADDR_ARRAY(mac));
13856
13857 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13858 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13859 status =
13860 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13861 }
13862 }
13863#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013864 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013865 return status;
13866}
13867
13868/**
13869 * wlan_hdd_cfg80211_add_station() - add station
13870 * @wiphy: Pointer to wiphy
13871 * @mac: Pointer to station mac address
13872 * @pmksa: Pointer to add station parameter
13873 *
13874 * Return: 0 for success, non-zero for failure
13875 */
13876#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13877static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13878 struct net_device *dev,
13879 const uint8_t *mac,
13880 struct station_parameters *params)
13881#else
13882static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13883 struct net_device *dev, uint8_t *mac,
13884 struct station_parameters *params)
13885#endif
13886{
13887 int ret;
13888
13889 cds_ssr_protect(__func__);
13890 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13891 cds_ssr_unprotect(__func__);
13892
13893 return ret;
13894}
13895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896/**
13897 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13898 * @wiphy: Pointer to wiphy
13899 * @dev: Pointer to network device
13900 * @pmksa: Pointer to set pmksa parameter
13901 *
13902 * Return: 0 for success, non-zero for failure
13903 */
13904static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13905 struct net_device *dev,
13906 struct cfg80211_pmksa *pmksa)
13907{
13908 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13909 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13910 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013911 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 int status;
13913 tPmkidCacheInfo pmk_id;
13914
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013915 ENTER();
13916
Anurag Chouhan6d760662016-02-20 16:05:43 +053013917 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013918 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919 return -EINVAL;
13920 }
13921
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013922 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13923 hdd_err("invalid session id: %d", pAdapter->sessionId);
13924 return -EINVAL;
13925 }
13926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013928 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013929 return -EINVAL;
13930 }
13931
13932 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013933 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934 pmksa->bssid, pmksa->pmkid);
13935 return -EINVAL;
13936 }
13937
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013938 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 MAC_ADDR_ARRAY(pmksa->bssid));
13940
13941 status = wlan_hdd_validate_context(pHddCtx);
13942
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013943 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013944 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945
13946 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13947
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013948 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13949 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950
13951 /* Add to the PMKSA ID Cache in CSR */
13952 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13953 &pmk_id, 1, false);
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_PMKSA,
13957 pAdapter->sessionId, result));
13958
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013959 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013960 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013961}
13962
13963/**
13964 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13965 * @wiphy: Pointer to wiphy
13966 * @dev: Pointer to network device
13967 * @pmksa: Pointer to set pmksa parameter
13968 *
13969 * Return: 0 for success, non-zero for failure
13970 */
13971static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13972 struct net_device *dev,
13973 struct cfg80211_pmksa *pmksa)
13974{
13975 int ret;
13976
13977 cds_ssr_protect(__func__);
13978 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13979 cds_ssr_unprotect(__func__);
13980
13981 return ret;
13982}
13983
13984/**
13985 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13986 * @wiphy: Pointer to wiphy
13987 * @dev: Pointer to network device
13988 * @pmksa: Pointer to pmksa parameter
13989 *
13990 * Return: 0 for success, non-zero for failure
13991 */
13992static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13993 struct net_device *dev,
13994 struct cfg80211_pmksa *pmksa)
13995{
13996 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13997 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13998 tHalHandle halHandle;
13999 int status = 0;
14000
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014001 ENTER();
14002
Anurag Chouhan6d760662016-02-20 16:05:43 +053014003 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014004 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014005 return -EINVAL;
14006 }
14007
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014008 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14009 hdd_err("invalid session id: %d", pAdapter->sessionId);
14010 return -EINVAL;
14011 }
14012
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014014 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014015 return -EINVAL;
14016 }
14017
14018 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014019 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020 return -EINVAL;
14021 }
14022
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014023 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014024 MAC_ADDR_ARRAY(pmksa->bssid));
14025
14026 status = wlan_hdd_validate_context(pHddCtx);
14027
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014028 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014029 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030
14031 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14032
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014033 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014034 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14035 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014037 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014038 sme_roam_del_pmkid_from_cache(halHandle,
14039 pAdapter->sessionId, pmksa->bssid,
14040 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014041 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 MAC_ADDR_ARRAY(pmksa->bssid));
14043 status = -EINVAL;
14044 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014045 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 return status;
14047}
14048
14049/**
14050 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14051 * @wiphy: Pointer to wiphy
14052 * @dev: Pointer to network device
14053 * @pmksa: Pointer to pmksa parameter
14054 *
14055 * Return: 0 for success, non-zero for failure
14056 */
14057static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14058 struct net_device *dev,
14059 struct cfg80211_pmksa *pmksa)
14060{
14061 int ret;
14062
14063 cds_ssr_protect(__func__);
14064 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14065 cds_ssr_unprotect(__func__);
14066
14067 return ret;
14068
14069}
14070
14071/**
14072 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14073 * @wiphy: Pointer to wiphy
14074 * @dev: Pointer to network device
14075 *
14076 * Return: 0 for success, non-zero for failure
14077 */
14078static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14079 struct net_device *dev)
14080{
14081 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14082 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14083 tHalHandle halHandle;
14084 int status = 0;
14085
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014086 ENTER();
14087
Anurag Chouhan6d760662016-02-20 16:05:43 +053014088 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014089 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014090 return -EINVAL;
14091 }
14092
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014093 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14094 hdd_err("invalid session id: %d", pAdapter->sessionId);
14095 return -EINVAL;
14096 }
14097
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014098 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099
14100 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14101 status = wlan_hdd_validate_context(pHddCtx);
14102
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014103 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014104 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014105
14106 /* Retrieve halHandle */
14107 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14108
14109 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014110 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014111 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14112 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014113 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 status = -EINVAL;
14115 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014116 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014117 return status;
14118}
14119
14120/**
14121 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14122 * @wiphy: Pointer to wiphy
14123 * @dev: Pointer to network device
14124 *
14125 * Return: 0 for success, non-zero for failure
14126 */
14127static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14128 struct net_device *dev)
14129{
14130 int ret;
14131
14132 cds_ssr_protect(__func__);
14133 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14134 cds_ssr_unprotect(__func__);
14135
14136 return ret;
14137}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014139#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014140/**
14141 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14142 * @wiphy: Pointer to wiphy
14143 * @dev: Pointer to network device
14144 * @ftie: Pointer to fast transition ie parameter
14145 *
14146 * Return: 0 for success, non-zero for failure
14147 */
14148static int
14149__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14150 struct net_device *dev,
14151 struct cfg80211_update_ft_ies_params *ftie)
14152{
14153 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14154 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14155 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14156 int status;
14157
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014158 ENTER();
14159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160 status = wlan_hdd_validate_context(hdd_ctx);
14161 if (status)
14162 return status;
14163
Anurag Chouhan6d760662016-02-20 16:05:43 +053014164 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014165 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014166 return -EINVAL;
14167 }
14168
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014169 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14170 hdd_err("invalid session id: %d", pAdapter->sessionId);
14171 return -EINVAL;
14172 }
14173
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014174 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014175 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14176 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14177 /* Added for debug on reception of Re-assoc Req. */
14178 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014179 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014180 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014181 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014182 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014183 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014184 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185
14186 /* Pass the received FT IEs to SME */
14187 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14188 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014189 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014190 return 0;
14191}
14192
14193/**
14194 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14195 * @wiphy: Pointer to wiphy
14196 * @dev: Pointer to network device
14197 * @ftie: Pointer to fast transition ie parameter
14198 *
14199 * Return: 0 for success, non-zero for failure
14200 */
14201static int
14202wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14203 struct net_device *dev,
14204 struct cfg80211_update_ft_ies_params *ftie)
14205{
14206 int ret;
14207
14208 cds_ssr_protect(__func__);
14209 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14210 cds_ssr_unprotect(__func__);
14211
14212 return ret;
14213}
14214#endif
14215
14216#ifdef WLAN_FEATURE_GTK_OFFLOAD
14217/**
14218 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14219 * @callbackContext: Callback context
14220 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14221 *
14222 * Callback rountine called upon receiving response for get offload info
14223 *
14224 * Return: none
14225 */
14226void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14227 tpSirGtkOffloadGetInfoRspParams
14228 pGtkOffloadGetInfoRsp)
14229{
14230 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14231 uint8_t tempReplayCounter[8];
14232 hdd_station_ctx_t *pHddStaCtx;
14233
14234 ENTER();
14235
14236 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014237 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238 return;
14239 }
14240
14241 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014242 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 return;
14244 }
14245
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014246 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014247 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014248 return;
14249 }
14250
14251 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14252 /* Update replay counter */
14253 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14254 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14255
14256 {
14257 /* changing from little to big endian since supplicant
14258 * works on big endian format
14259 */
14260 int i;
14261 uint8_t *p =
14262 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14263
14264 for (i = 0; i < 8; i++) {
14265 tempReplayCounter[7 - i] = (uint8_t) p[i];
14266 }
14267 }
14268
14269 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014270 cfg80211_gtk_rekey_notify(pAdapter->dev,
14271 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014272 tempReplayCounter, GFP_KERNEL);
14273}
14274
14275/**
14276 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14277 * @wiphy: Pointer to wiphy
14278 * @dev: Pointer to network device
14279 * @data: Pointer to rekey data
14280 *
14281 * This function is used to offload GTK rekeying job to the firmware.
14282 *
14283 * Return: 0 for success, non-zero for failure
14284 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014285static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014286int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14287 struct net_device *dev,
14288 struct cfg80211_gtk_rekey_data *data)
14289{
14290 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14291 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14292 hdd_station_ctx_t *pHddStaCtx;
14293 tHalHandle hHal;
14294 int result;
14295 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014296 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014297
14298 ENTER();
14299
Anurag Chouhan6d760662016-02-20 16:05:43 +053014300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014301 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014302 return -EINVAL;
14303 }
14304
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014305 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14306 hdd_err("invalid session id: %d", pAdapter->sessionId);
14307 return -EINVAL;
14308 }
14309
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014310 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014311 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14312 pAdapter->sessionId, pAdapter->device_mode));
14313
14314 result = wlan_hdd_validate_context(pHddCtx);
14315
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014316 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318
14319 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14320 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14321 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014322 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 return -EAGAIN;
14324 }
14325
14326 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14327 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14328 NL80211_KCK_LEN);
14329 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14330 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014331 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014332 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 {
14334 /* changing from big to little endian since driver
14335 * works on little endian format
14336 */
14337 uint8_t *p =
14338 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14339 ullKeyReplayCounter;
14340 int i;
14341
14342 for (i = 0; i < 8; i++) {
14343 p[7 - i] = data->replay_ctr[i];
14344 }
14345 }
14346
14347 if (true == pHddCtx->hdd_wlan_suspended) {
14348 /* if wlan is suspended, enable GTK offload directly from here */
14349 memcpy(&hddGtkOffloadReqParams,
14350 &pHddStaCtx->gtkOffloadReqParams,
14351 sizeof(tSirGtkOffloadParams));
14352 status =
14353 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14354 pAdapter->sessionId);
14355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014356 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014357 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014358 status);
14359 return -EINVAL;
14360 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014361 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014363 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014365 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014366 return result;
14367}
14368
14369/**
14370 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14371 * @wiphy: Pointer to wiphy
14372 * @dev: Pointer to network device
14373 * @data: Pointer to rekey data
14374 *
14375 * This function is used to offload GTK rekeying job to the firmware.
14376 *
14377 * Return: 0 for success, non-zero for failure
14378 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014379static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14381 struct net_device *dev,
14382 struct cfg80211_gtk_rekey_data *data)
14383{
14384 int ret;
14385
14386 cds_ssr_protect(__func__);
14387 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14388 cds_ssr_unprotect(__func__);
14389
14390 return ret;
14391}
14392#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14393
14394/**
14395 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14396 * @wiphy: Pointer to wiphy
14397 * @dev: Pointer to network device
14398 * @param: Pointer to access control parameter
14399 *
14400 * Return: 0 for success, non-zero for failure
14401 */
14402static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14403 struct net_device *dev,
14404 const struct cfg80211_acl_data *params)
14405{
14406 int i;
14407 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14408 hdd_hostapd_state_t *pHostapdState;
14409 tsap_Config_t *pConfig;
14410 v_CONTEXT_t p_cds_context = NULL;
14411 hdd_context_t *pHddCtx;
14412 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014413 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414
14415 ENTER();
14416
Anurag Chouhan6d760662016-02-20 16:05:43 +053014417 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014418 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014419 return -EINVAL;
14420 }
14421
14422 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014423 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014424 return -EINVAL;
14425 }
14426
14427 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14428 status = wlan_hdd_validate_context(pHddCtx);
14429
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014430 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014431 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014432
14433 p_cds_context = pHddCtx->pcds_context;
14434 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14435
14436 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014437 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014438 return -EINVAL;
14439 }
14440
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014441 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014442 params->n_acl_entries);
14443
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014444 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014445 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14446 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014447 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014448 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14449
14450 /* default value */
14451 pConfig->num_accept_mac = 0;
14452 pConfig->num_deny_mac = 0;
14453
14454 /**
14455 * access control policy
14456 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14457 * listed in hostapd.deny file.
14458 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14459 * listed in hostapd.accept file.
14460 */
14461 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14462 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14463 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14464 params->acl_policy) {
14465 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14466 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014467 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014468 params->acl_policy);
14469 return -ENOTSUPP;
14470 }
14471
14472 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14473 pConfig->num_accept_mac = params->n_acl_entries;
14474 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014475 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14476 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477 MAC_ADDR_ARRAY(
14478 params->mac_addrs[i].addr));
14479
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014480 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 params->mac_addrs[i].addr,
14482 sizeof(qcmacaddr));
14483 }
14484 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14485 pConfig->num_deny_mac = params->n_acl_entries;
14486 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014487 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14488 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014489 MAC_ADDR_ARRAY(
14490 params->mac_addrs[i].addr));
14491
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014492 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014493 params->mac_addrs[i].addr,
14494 sizeof(qcmacaddr));
14495 }
14496 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014497 qdf_status = wlansap_set_mac_acl(
14498 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014499 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014500 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014501 return -EINVAL;
14502 }
14503 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014504 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014505 hdd_device_mode_to_string(pAdapter->device_mode),
14506 pAdapter->device_mode);
14507 return -EINVAL;
14508 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014509 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510 return 0;
14511}
14512
14513/**
14514 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14515 * __wlan_hdd_cfg80211_set_mac_acl
14516 * @wiphy: pointer to wiphy structure
14517 * @dev: pointer to net_device
14518 * @params: pointer to cfg80211_acl_data
14519 *
14520 * Return; 0 on success, error number otherwise
14521 */
14522static int
14523wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14524 struct net_device *dev,
14525 const struct cfg80211_acl_data *params)
14526{
14527 int ret;
14528
14529 cds_ssr_protect(__func__);
14530 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14531 cds_ssr_unprotect(__func__);
14532
14533 return ret;
14534}
14535
14536#ifdef WLAN_NL80211_TESTMODE
14537#ifdef FEATURE_WLAN_LPHB
14538/**
14539 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14540 * @pHddCtx: Pointer to hdd context
14541 * @lphbInd: Pointer to low power heart beat indication parameter
14542 *
14543 * Return: none
14544 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014545static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14546 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547{
14548 struct sk_buff *skb;
14549
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014550 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014552 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554
14555 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014556 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014557 return;
14558 }
14559
14560 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14561 wiphy, sizeof(tSirLPHBInd),
14562 GFP_ATOMIC);
14563 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014564 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 return;
14566 }
14567
14568 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014569 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014570 goto nla_put_failure;
14571 }
14572 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014573 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574 goto nla_put_failure;
14575 }
14576 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014577 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578 goto nla_put_failure;
14579 }
14580 cfg80211_testmode_event(skb, GFP_ATOMIC);
14581 return;
14582
14583nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014584 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014585 kfree_skb(skb);
14586
14587 return;
14588}
14589#endif /* FEATURE_WLAN_LPHB */
14590
14591/**
14592 * __wlan_hdd_cfg80211_testmode() - test mode
14593 * @wiphy: Pointer to wiphy
14594 * @data: Data pointer
14595 * @len: Data length
14596 *
14597 * Return: 0 for success, non-zero for failure
14598 */
14599static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14600 void *data, int len)
14601{
14602 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14603 int err;
14604 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14605
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014606 ENTER();
14607
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 err = wlan_hdd_validate_context(pHddCtx);
14609 if (err)
14610 return err;
14611
14612 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14613 len, wlan_hdd_tm_policy);
14614 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014615 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014616 return err;
14617 }
14618
14619 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014620 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 return -EINVAL;
14622 }
14623
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014624 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014625 TRACE_CODE_HDD_CFG80211_TESTMODE,
14626 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14628#ifdef FEATURE_WLAN_LPHB
14629 /* Low Power Heartbeat configuration request */
14630 case WLAN_HDD_TM_CMD_WLAN_HB:
14631 {
14632 int buf_len;
14633 void *buf;
14634 tSirLPHBReq *hb_params = NULL;
14635 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014636 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014637
14638 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014639 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014640 return -EINVAL;
14641 }
14642
14643 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14644 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14645
14646 hb_params_temp = (tSirLPHBReq *) buf;
14647 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14648 && (hb_params_temp->params.lphbTcpParamReq.
14649 timePeriodSec == 0))
14650 return -EINVAL;
14651
14652 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014653 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014654 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014655 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 return -ENOMEM;
14657 }
14658
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014659 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660 smeStatus =
14661 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14662 hb_params,
14663 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014664 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014665 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014666 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014667 }
14668 return 0;
14669 }
14670#endif /* FEATURE_WLAN_LPHB */
14671
14672#if defined(QCA_WIFI_FTM)
14673 case WLAN_HDD_TM_CMD_WLAN_FTM:
14674 {
14675 int buf_len;
14676 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014677 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014679 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014680 return -EINVAL;
14681 }
14682
14683 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14684 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14685
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014686 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687
14688 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14689
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014690 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 err = -EBUSY;
14692 break;
14693 }
14694#endif
14695
14696 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014697 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14699 return -EOPNOTSUPP;
14700 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014701 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014702 return err;
14703}
14704
14705/**
14706 * wlan_hdd_cfg80211_testmode() - test mode
14707 * @wiphy: Pointer to wiphy
14708 * @dev: Pointer to network device
14709 * @data: Data pointer
14710 * @len: Data length
14711 *
14712 * Return: 0 for success, non-zero for failure
14713 */
14714static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14715#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14716 struct wireless_dev *wdev,
14717#endif
14718 void *data, int len)
14719{
14720 int ret;
14721
14722 cds_ssr_protect(__func__);
14723 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14724 cds_ssr_unprotect(__func__);
14725
14726 return ret;
14727}
14728
14729#if defined(QCA_WIFI_FTM)
14730/**
14731 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14732 * @buf: Pointer to buffer
14733 * @buf_len: Buffer length
14734 *
14735 * Return: none
14736 */
14737void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14738{
14739 struct sk_buff *skb;
14740 hdd_context_t *hdd_ctx;
14741
14742 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014743 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014744 return;
14745 }
14746
Anurag Chouhan6d760662016-02-20 16:05:43 +053014747 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014749 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 return;
14751 }
14752
14753 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14754 buf_len, GFP_KERNEL);
14755 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014756 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014757 return;
14758 }
14759
14760 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14761 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14762 goto nla_put_failure;
14763
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014764 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765
14766 cfg80211_testmode_event(skb, GFP_KERNEL);
14767 return;
14768
14769nla_put_failure:
14770 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014771 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772}
14773#endif
14774#endif /* CONFIG_NL80211_TESTMODE */
14775
14776#ifdef QCA_HT_2040_COEX
14777/**
14778 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14779 * @wiphy: Pointer to wiphy
14780 * @dev: Pointer to network device
14781 * @chandef: Pointer to channel definition parameter
14782 *
14783 * Return: 0 for success, non-zero for failure
14784 */
14785static int
14786__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14787 struct net_device *dev,
14788 struct cfg80211_chan_def *chandef)
14789{
14790 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14791 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014792 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014793 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014794 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795
Anurag Chouhan6d760662016-02-20 16:05:43 +053014796 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014797 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 return -EINVAL;
14799 }
14800
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014801 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14802 hdd_err("invalid session id: %d", pAdapter->sessionId);
14803 return -EINVAL;
14804 }
14805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14807 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014808 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014811 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 sme_get_config_param(pHddCtx->hHal, &sme_config);
14813 switch (chandef->width) {
14814 case NL80211_CHAN_WIDTH_20:
14815 if (sme_config.csrConfig.channelBondingMode24GHz !=
14816 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14817 sme_config.csrConfig.channelBondingMode24GHz =
14818 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14819 sme_update_config(pHddCtx->hHal, &sme_config);
14820 cbModeChange = true;
14821 }
14822 break;
14823
14824 case NL80211_CHAN_WIDTH_40:
14825 if (sme_config.csrConfig.channelBondingMode24GHz ==
14826 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14827 if (NL80211_CHAN_HT40MINUS ==
14828 cfg80211_get_chandef_type(chandef))
14829 sme_config.csrConfig.channelBondingMode24GHz =
14830 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14831 else
14832 sme_config.csrConfig.channelBondingMode24GHz =
14833 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14834 sme_update_config(pHddCtx->hHal, &sme_config);
14835 cbModeChange = true;
14836 }
14837 break;
14838
14839 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014840 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014841 return -EINVAL;
14842 }
14843
14844 if (!cbModeChange)
14845 return 0;
14846
Krunal Sonib4326f22016-03-10 13:05:51 -080014847 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014848 return 0;
14849
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014850 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014851 sme_config.csrConfig.channelBondingMode24GHz);
14852
14853 /* Change SAP ht2040 mode */
14854 status = hdd_set_sap_ht2040_mode(pAdapter,
14855 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014856 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014857 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014858 return -EINVAL;
14859 }
14860
14861 return 0;
14862}
14863
14864/**
14865 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14866 * @wiphy: Pointer to wiphy
14867 * @dev: Pointer to network device
14868 * @chandef: Pointer to channel definition parameter
14869 *
14870 * Return: 0 for success, non-zero for failure
14871 */
14872static int
14873wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14874 struct net_device *dev,
14875 struct cfg80211_chan_def *chandef)
14876{
14877 int ret;
14878
14879 cds_ssr_protect(__func__);
14880 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14881 cds_ssr_unprotect(__func__);
14882
14883 return ret;
14884}
14885#endif
14886
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014887#ifdef CHANNEL_SWITCH_SUPPORTED
14888/**
14889 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14890 * channel in SAP/GO
14891 * @wiphy: wiphy pointer
14892 * @dev: dev pointer.
14893 * @csa_params: Change channel params
14894 *
14895 * This function is called to switch channel in SAP/GO
14896 *
14897 * Return: 0 if success else return non zero
14898 */
14899static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14900 struct net_device *dev,
14901 struct cfg80211_csa_settings *csa_params)
14902{
14903 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14904 hdd_context_t *hdd_ctx;
14905 uint8_t channel;
14906 uint16_t freq;
14907 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014908 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014909
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014910 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014911 csa_params->chandef.chan->center_freq);
14912
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014913 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
14914 hdd_err("invalid session id: %d", adapter->sessionId);
14915 return -EINVAL;
14916 }
14917
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014918 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14919 ret = wlan_hdd_validate_context(hdd_ctx);
14920
14921 if (0 != ret)
14922 return ret;
14923
Krunal Sonib4326f22016-03-10 13:05:51 -080014924 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14925 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014926 return -ENOTSUPP;
14927
14928 freq = csa_params->chandef.chan->center_freq;
14929 channel = cds_freq_to_chan(freq);
14930
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014931 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14932
14933 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014934 return ret;
14935}
14936
14937/**
14938 * wlan_hdd_cfg80211_channel_switch()- function to switch
14939 * channel in SAP/GO
14940 * @wiphy: wiphy pointer
14941 * @dev: dev pointer.
14942 * @csa_params: Change channel params
14943 *
14944 * This function is called to switch channel in SAP/GO
14945 *
14946 * Return: 0 if success else return non zero
14947 */
14948static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14949 struct net_device *dev,
14950 struct cfg80211_csa_settings *csa_params)
14951{
14952 int ret;
14953
14954 cds_ssr_protect(__func__);
14955 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14956 cds_ssr_unprotect(__func__);
14957 return ret;
14958}
14959#endif
14960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014961/**
14962 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14963 * translation from NL to policy manager type
14964 * @type: Generic connection mode type defined in NL
14965 *
14966 *
14967 * This function provides the type translation
14968 *
14969 * Return: cds_con_mode enum
14970 */
14971enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14972 enum nl80211_iftype type)
14973{
14974 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14975 switch (type) {
14976 case NL80211_IFTYPE_STATION:
14977 mode = CDS_STA_MODE;
14978 break;
14979 case NL80211_IFTYPE_P2P_CLIENT:
14980 mode = CDS_P2P_CLIENT_MODE;
14981 break;
14982 case NL80211_IFTYPE_P2P_GO:
14983 mode = CDS_P2P_GO_MODE;
14984 break;
14985 case NL80211_IFTYPE_AP:
14986 mode = CDS_SAP_MODE;
14987 break;
14988 case NL80211_IFTYPE_ADHOC:
14989 mode = CDS_IBSS_MODE;
14990 break;
14991 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014992 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014993 type);
14994 }
14995 return mode;
14996}
14997
14998/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014999 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15000 * @wiphy: Handle to struct wiphy to get handle to module context.
15001 * @chandef: Contains information about the capture channel to be set.
15002 *
15003 * This interface is called if and only if monitor mode interface alone is
15004 * active.
15005 *
15006 * Return: 0 success or error code on failure.
15007 */
15008static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15009 struct cfg80211_chan_def *chandef)
15010{
15011 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15012 hdd_adapter_t *adapter;
15013 hdd_station_ctx_t *sta_ctx;
15014 struct hdd_mon_set_ch_info *ch_info;
15015 QDF_STATUS status;
15016 tHalHandle hal_hdl;
15017 struct qdf_mac_addr bssid;
15018 tCsrRoamProfile roam_profile;
15019 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015020 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015021 int ret;
15022 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15023
15024 ENTER();
15025
15026 ret = wlan_hdd_validate_context(hdd_ctx);
15027 if (ret)
15028 return ret;
15029
15030 hal_hdl = hdd_ctx->hHal;
15031
15032 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15033 if (!adapter)
15034 return -EIO;
15035
15036 hdd_info("%s: set monitor mode Channel %d and freq %d",
15037 adapter->dev->name, chan_num, chandef->chan->center_freq);
15038
15039 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15040 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015041 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15042 roam_profile.ChannelInfo.numOfChannels = 1;
15043 roam_profile.phyMode = ch_info->phy_mode;
15044 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015045 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015046
15047 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15048 QDF_MAC_ADDR_SIZE);
15049
15050 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015051 /*
15052 * CDS api expects secondary channel for calculating
15053 * the channel params
15054 */
15055 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15056 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15057 if (chan_num >= 1 && chan_num <= 5)
15058 sec_ch = chan_num + 4;
15059 else if (chan_num >= 6 && chan_num <= 13)
15060 sec_ch = chan_num - 4;
15061 }
15062 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015063 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15064 &roam_profile);
15065 if (status) {
15066 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15067 status);
15068 ret = qdf_status_to_os_return(status);
15069 return ret;
15070 }
15071 EXIT();
15072 return 0;
15073}
15074
15075/**
15076 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15077 * @wiphy: Handle to struct wiphy to get handle to module context.
15078 * @chandef: Contains information about the capture channel to be set.
15079 *
15080 * This interface is called if and only if monitor mode interface alone is
15081 * active.
15082 *
15083 * Return: 0 success or error code on failure.
15084 */
15085static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15086 struct cfg80211_chan_def *chandef)
15087{
15088 int ret;
15089
15090 cds_ssr_protect(__func__);
15091 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15092 cds_ssr_unprotect(__func__);
15093 return ret;
15094}
15095
15096/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015097 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15098 * @adapter: pointer to adapter
15099 *
15100 * Wrapper function to clear link layer stats.
15101 * return - void
15102 */
15103void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15104{
15105 tSirLLStatsClearReq link_layer_stats_clear_req;
15106 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15107
Mukul Sharma491021c2016-09-29 21:39:19 +053015108 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15109 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015110 link_layer_stats_clear_req.stopReq = 0;
15111 link_layer_stats_clear_req.reqId = 1;
15112 link_layer_stats_clear_req.staId = adapter->sessionId;
15113 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15114
15115 return;
15116}
15117
15118/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015119 * struct cfg80211_ops - cfg80211_ops
15120 *
15121 * @add_virtual_intf: Add virtual interface
15122 * @del_virtual_intf: Delete virtual interface
15123 * @change_virtual_intf: Change virtual interface
15124 * @change_station: Change station
15125 * @add_beacon: Add beacon in sap mode
15126 * @del_beacon: Delete beacon in sap mode
15127 * @set_beacon: Set beacon in sap mode
15128 * @start_ap: Start ap
15129 * @change_beacon: Change beacon
15130 * @stop_ap: Stop ap
15131 * @change_bss: Change bss
15132 * @add_key: Add key
15133 * @get_key: Get key
15134 * @del_key: Delete key
15135 * @set_default_key: Set default key
15136 * @set_channel: Set channel
15137 * @scan: Scan
15138 * @connect: Connect
15139 * @disconnect: Disconnect
15140 * @join_ibss = Join ibss
15141 * @leave_ibss = Leave ibss
15142 * @set_wiphy_params = Set wiphy params
15143 * @set_tx_power = Set tx power
15144 * @get_tx_power = get tx power
15145 * @remain_on_channel = Remain on channel
15146 * @cancel_remain_on_channel = Cancel remain on channel
15147 * @mgmt_tx = Tx management frame
15148 * @mgmt_tx_cancel_wait = Cancel management tx wait
15149 * @set_default_mgmt_key = Set default management key
15150 * @set_txq_params = Set tx queue parameters
15151 * @get_station = Get station
15152 * @set_power_mgmt = Set power management
15153 * @del_station = Delete station
15154 * @add_station = Add station
15155 * @set_pmksa = Set pmksa
15156 * @del_pmksa = Delete pmksa
15157 * @flush_pmksa = Flush pmksa
15158 * @update_ft_ies = Update FT IEs
15159 * @tdls_mgmt = Tdls management
15160 * @tdls_oper = Tdls operation
15161 * @set_rekey_data = Set rekey data
15162 * @sched_scan_start = Scheduled scan start
15163 * @sched_scan_stop = Scheduled scan stop
15164 * @resume = Resume wlan
15165 * @suspend = Suspend wlan
15166 * @set_mac_acl = Set mac acl
15167 * @testmode_cmd = Test mode command
15168 * @set_ap_chanwidth = Set AP channel bandwidth
15169 * @dump_survey = Dump survey
15170 * @key_mgmt_set_pmk = Set pmk key management
15171 */
15172static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15173 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15174 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15175 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15176 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015177 .start_ap = wlan_hdd_cfg80211_start_ap,
15178 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15179 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015180 .change_bss = wlan_hdd_cfg80211_change_bss,
15181 .add_key = wlan_hdd_cfg80211_add_key,
15182 .get_key = wlan_hdd_cfg80211_get_key,
15183 .del_key = wlan_hdd_cfg80211_del_key,
15184 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15185 .scan = wlan_hdd_cfg80211_scan,
15186 .connect = wlan_hdd_cfg80211_connect,
15187 .disconnect = wlan_hdd_cfg80211_disconnect,
15188 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15189 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15190 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15191 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15192 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15193 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15194 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15195 .mgmt_tx = wlan_hdd_mgmt_tx,
15196 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15197 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15198 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015199 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015200 .get_station = wlan_hdd_cfg80211_get_station,
15201 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15202 .del_station = wlan_hdd_cfg80211_del_station,
15203 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15205 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15206 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015207#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15209#endif
15210#ifdef FEATURE_WLAN_TDLS
15211 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15212 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15213#endif
15214#ifdef WLAN_FEATURE_GTK_OFFLOAD
15215 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15216#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15217#ifdef FEATURE_WLAN_SCAN_PNO
15218 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15219 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15220#endif /*FEATURE_WLAN_SCAN_PNO */
15221 .resume = wlan_hdd_cfg80211_resume_wlan,
15222 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15223 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15224#ifdef WLAN_NL80211_TESTMODE
15225 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15226#endif
15227#ifdef QCA_HT_2040_COEX
15228 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15229#endif
15230 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015231#ifdef CHANNEL_SWITCH_SUPPORTED
15232 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15233#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015234 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015235#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15236 defined(CFG80211_ABORT_SCAN)
15237 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15238#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015239};